ブログ

割とコンピュータよりの情報をお届けします。

WPF

Windows Embedded でのMessageBoxの扱いの注意

Windows Embedded Standard向けのアプリを開発していたら,.NETで64bitでも32bitでもどちらでもアプリが動かしるようにしていたところ,32bitでの動作では普通にMessageBoxが開くのに...

組み込み用のWindowsではWindows標準のMessageBoxの動作を変更することができる.すべてOKを応答させてダイアログを表示させないようにするのだ.

.NET Frameworkで開発したアプリで特に64bitで動かしたときにできるらしい.
この機能は開発時にMessageBoxを出させておいて,展開時にはMessageBoxを抑制するというという使い方になる.
知らなかったのでダイアログが出ない理由を一週間かけて探した.

≫ Read More

2019/10/19 コンピュータ   TakeMe

Live ChartsでScatter Plotに線が付かない仕様 Vol. 2

前回の記事ではX, Yのデータを含むモデルを新たに起こしているが,x, yだけなら標準ではObservablePointも使用できるので一部訂正

つまり,ObservablePointを使うと,前回のXYPointModelはわざわざつけなくて良い.
ChartValuesはListでもよいらしいが確認していない.
実はこの例では以下のようにデータグリッドを追加するとデータグリッド上での変更がチャートに反映されるということになっている.
<DataGrid ItemsSource="{Binding listXYPoint}" FontSize="20"/>
まあ使うかどうかはべつですが

using MahApps.Metro.Controls;
using LiveCharts;
using LiveCharts.Wpf;
using LiveCharts.Configurations;
using LiveCharts.Defaults;

namespace LiveChartsTEST
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : MetroWindow
    {
        public MainWindow()
        {
            InitializeComponent();

            ChartData cd = new ChartData();

            var sc = new SeriesCollection()
            {
                new LineSeries
                {
                    LineSmoothness = 0,
                    Values = cd.listXYPoint
                }
            };

            cd.seriesCollection = sc;
            this.DataContext = cd;
        }

        public class ChartData
        {
            public SeriesCollection seriesCollection { get; set; }
            public ChartValues<ObservablePoint> listXYPoint { get; set; } = new ChartValues<ObservablePoint>();
            public ChartData()
            {
                for (int i = 0; i < 10; i++)
                {
                    listXYPoint.Add(new ObservablePoint(i, i * i));
                }
            }
        }
    }
}

≫ Read More

2019/09/09 コンピュータ   TakeMe
Tag:WPF

Live ChartsでScatter Plotに線が付かない仕様

Live Charts WPFを使い始めた.
Line ChartとScatter Plotはそれぞれあるが,どうしてだろう 2つを組み合わせて使用する方法が書いていない.

Live Chartsに関してGitHubで質問が上がっていた.
https://github.com/Live-Charts/Live-Charts/issues/737
結局のところ2019年初の段階で 質問にまともに答えていないのだ.

ところが,現在Tutorial and Examples (https://lvcharts.net/App/examples/v1/wpf/Date%20Time)がようやく追い付いてきたようだ.サンプルではDateTimeを横軸に設定しているが,doubleに置き換えることは当然可能である.例えば以下のように行う(MahAppsも一緒に使っているが必須ではないのはご存じの通りです).

using MahApps.Metro.Controls;
using LiveCharts;
using LiveCharts.Wpf;
using LiveCharts.Configurations;

namespace LiveChartsTEST
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : MetroWindow
    {
        public MainWindow()
        {
            InitializeComponent();

            ChartData cd = new ChartData();

            var xypointConfig = Mappers.Xy<XYPointModel>()
                .X(model => model.ValueX)
                .Y(model => model.ValueY);

            var sc = new SeriesCollection(xypointConfig)
            {
                new LineSeries
                {
                    Values = new ChartValues<XYPointModel>
                    {
                        new XYPointModel
                        {
                            ValueX = 0,
                            ValueY = 5
                        },
                        new XYPointModel
                        {
                            ValueX = 10,
                            ValueY = 9
                        }
                    }
                }
            };

            cd.seriesCollection = sc;
            this.DataContext = cd;
        }

        public class ChartData
        {
            public SeriesCollection seriesCollection { get; set; }
        }

        public class XYPointModel
        {
            public double ValueX { get; set; }
            public double ValueY { get; set; }
        }
    }
}

XAMLについて以下のようにしておくなど 必要かも

<lvc:CartesianChart Series="{Binding seriesCollection}" LegendLocation="Bottom" />

≫ Read More

2019/09/08 コンピュータ   TakeMe
Tag:WPF

WPFのメモリリーク対策

C#ではメモリリークはほとんど心配ないと思っていたが,WPFアプリケーションを作っていると,メモリリークが頻繁に起きることが分かって恐ろしくなった.

まず,参考のページ「俺が遭遇したWPFイメージコントロールのメモリーリークと回避法(?)の1つ」を参考にすると,Imageコントロールはよくリークを起こす.参考のページのサンプルコードの最後の方にあるように,明示的にSourceにnullを入れてやらないと割と残るようだ.

リーク以外に,キャッシュという仕組みもありわかりにくい.xamlにイメージのファイル名を直接書いていると一度使ったイメージはキャッシュされ次の使用が速くなる(らしい).

このほか,UserControlもうまく設計していない場合,リークを起こす.Imageを使う場合やTimerを使う場合にはIDisposalインタフェースを実装して明示的にDisposeを呼び出すことを強く推奨する.TimerなんかはいったんStartしたままコントロールを破棄してしまうと(Windowを閉じるなど),一見コントロールが使えなくなくなっても残ってしまう.しかも,消えるタイミングが不定で恐ろしいバグになる(たいていはtickも残る).

Visual Studio 2017 ProfessionalやCommunityなら診断ツールを用いてヒープを表示させると,参照しているオブジェクト種類の一覧と参照されているオブジェクトの一覧が取れるのでデバッグの助けになる.
ポイントはImageが残っていないか?Start()を呼んだままのTimerが残っていないか?かな

≫ Read More

2019/02/13 日記   TakeMe
Tag:WPF

WPFでTextBox内で上下キーでフォーカスを遷移

WPFでTextBoxにフォーカスが当たっているときに上下キーを押すとフォーカスを遷移できる仕組みを実装していた。

xamlにはTextBoxが複数並べた。
そのTextBoxにはKeyUpのイベントハンドラを設定している。

<TextBox HorizontalAlignment="Left" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120" KeyUp="TextBox_KeyUpEvent"/>

コードビハインドでは以下のように設定を追加してみた。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApp1
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void TextBox_KeyUpEvent(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Down)
            {
                var direction = FocusNavigationDirection.Next;
                (FocusManager.GetFocusedElement(this) as FrameworkElement)?.MoveFocus(new TraversalRequest(direction));
            } else if (e.Key == Key.Up)
            {
                var direction = FocusNavigationDirection.Previous;
                (FocusManager.GetFocusedElement(this) as FrameworkElement)?.MoveFocus(new TraversalRequest(direction));
            }
        }
    }
}

FocusNavigationDirection.Nextとか,FocusNavigationDirection.Previousとかはよいが,?を使った書法は参考ページにあったものだが,珍しい書き方だったので引用してしまった。
もし私がコーディングしたら以下のようになる(かな)

private void TextBox_KeyUpEvent(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Down)
            {
                var direction = FocusNavigationDirection.Next;
                FrameworkElement element = (FrameworkElement)FocusManager.GetFocusedElement(this);
                if (element != null)
                    element.MoveFocus(new TraversalRequest(direction));
            } else if (e.Key == Key.Up)
            {
                var direction = FocusNavigationDirection.Previous;
                FrameworkElement element = (FrameworkElement)FocusManager.GetFocusedElement(this);
                if (element != null)
                    element.MoveFocus(new TraversalRequest(direction));
            }
        }

≫ Read More

2018/10/13 コンピュータ   TakeMe
Tag:WPF