前提・実現したいこと
DataGridのセルに波形を描画するために試行錯誤している内容です。
描画にあたってセルの実寸が必要になるので
今回の目的は「各行の該当セルのサイズ(あるいは内部のサイズ)を常に把握する」ことです。
発生している問題・エラーメッセージ
最初に起動した時点で目に見えているセルのサイズ取得はできているものの
下にスクロールして隠れていた行を表示させると、適切に取得できていないことがわかりました。
2種類のやり方で試してみましたがいずれも安定しませんでした。
1.TemplateColumnにGrid継承コントロールをタテヨコStretchで配置し、そのRenderSizeをSizeChangedイベント発生時に取得する
2.DataGridCellにEventSetterでSizeChangedイベントを置き、そこから取得
DataGridにバインドしたリストで各行の該当セルのサイズを表示させています。
いずれにしても次の画像の通り、先頭数行は数値が代入されているのに下のほうは0のままです。
RenderSizeを取得しているため、見た目通りのサイズが代入されるはずという想定でした。
しっかり青い領域(NewGrid)が見えているのに高さ幅の値が0のままなのはなぜでしょうか。
コードの問題点、解決策があればお願いいたします。
該当のソースコード
C#
1using System; 2using System.Collections.Generic; 3using System.Windows; 4using System.ComponentModel; 5using System.Diagnostics; 6using System.Windows.Controls; 7 8 9namespace TestApp 10{ 11 /// <summary> 12 /// Interaction logic for MainWindow.xaml 13 /// </summary> 14 public partial class MainWindow : Window, INotifyPropertyChanged 15 { 16 public MainWindow() 17 { 18 InitializeComponent(); 19 20 this.DataContext = this; 21 22 } 23 24 //変更通知 25 public event PropertyChangedEventHandler PropertyChanged; 26 private void OnPropertyChanged(string propertyName) 27 { 28 this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 29 } 30 31 32 33 public List<Item> list 34 { 35 get 36 { 37 return _list; 38 } 39 set 40 { 41 _list = value; 42 OnPropertyChanged("list"); 43 } 44 } 45 List<Item> _list; 46 47 48 private void Window_ContentRendered(object sender, EventArgs e) 49 { 50 List<Item> l = new List<Item>(); 51 for (int i = 0; i < 10; i++) 52 { 53 l.Add(new Item()); 54 } 55 56 list = l; 57 58 } 59 60 //2番目のやり方用 61 private void Cell_SizedChanged(object sender, SizeChangedEventArgs e) 62 { 63 DataGridCell c = (DataGridCell)sender; 64 DataGridRow r = DataGridRow.GetRowContainingElement(c); 65 66 ((List<Item>)dataGrid.ItemsSource)[r.GetIndex()].gridSize = c.RenderSize; 67 } 68 69 } 70} 71
XAML
1<Window x:Class="TestApp.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 5 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 6 xmlns:local="clr-namespace:TestApp" 7 mc:Ignorable="d" 8 Title="MainWindow" Height="450" Width="800" ContentRendered="Window_ContentRendered"> 9 10 <DataGrid x:Name="dataGrid" ScrollViewer.CanContentScroll="True" ItemsSource="{Binding list}" RowHeight="100" AutoGenerateColumns="False"> 11 <DataGrid.Columns> 12 <DataGridTemplateColumn x:Name="WaveColumn" Header="波形" Width="200" IsReadOnly="True"> 13 <DataGridTemplateColumn.CellTemplate> 14 <DataTemplate> 15 <!--1番目のやり方用--> 16 <local:NewGrid HorizontalAlignment="Stretch" 17 VerticalAlignment="Stretch" 18 Background="Aqua" 19 GridSize="{Binding gridSize, Mode=OneWayToSource, UpdateSourceTrigger=PropertyChanged}"/> 20 </DataTemplate> 21 </DataGridTemplateColumn.CellTemplate> 22 23 <!--2番目のやり方用--> 24 <DataGridTemplateColumn.CellStyle> 25 <Style TargetType="DataGridCell"> 26 <EventSetter Event="SizeChanged" Handler="Cell_SizedChanged" /> 27 </Style> 28 </DataGridTemplateColumn.CellStyle> 29 </DataGridTemplateColumn> 30 <DataGridTextColumn Binding="{Binding height}" Width="100" Header="height"/> 31 <DataGridTextColumn Binding="{Binding width}" Width="100" Header="width"/> 32 </DataGrid.Columns> 33 </DataGrid> 34</Window> 35
DataGridにバインドしたリストの項目
C#
1using System.Windows; 2using System.ComponentModel; 3 4namespace TestApp 5{ 6 public class Item : INotifyPropertyChanged 7 { 8 public int height 9 { 10 get 11 { 12 return _height; 13 } 14 set 15 { 16 _height = value; 17 OnPropertyChanged("height"); 18 } 19 } 20 21 int _height; 22 23 public int width 24 { 25 get 26 { 27 return _width; 28 } 29 set 30 { 31 _width = value; 32 OnPropertyChanged("width"); 33 } 34 } 35 36 int _width; 37 38 public Size gridSize 39 { 40 get 41 { 42 return new Size(width, height); 43 } 44 set 45 { 46 if (value.Height != 0.0) 47 { 48 width = (int)value.Width; 49 height = (int)value.Height; 50 } 51 } 52 } 53 54 public event PropertyChangedEventHandler PropertyChanged; 55 private void OnPropertyChanged(string propertyName) 56 { 57 this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 58 } 59 } 60} 61
Gridを継承したNewGrid
DependencyPropertyを登録してRenderSizeを間接的にバインドできるようにしたもの
C#
1 2using System.Windows; 3using System.Windows.Controls; 4using System.Diagnostics; 5 6namespace TestApp 7{ 8 public class NewGrid : Grid 9 { 10 public NewGrid() 11 : base() 12 { 13 SizeChanged += new SizeChangedEventHandler(NewGrid_SizeChanged); 14 } 15 16 void NewGrid_SizeChanged(object sender, SizeChangedEventArgs e) 17 { 18 GridSize = RenderSize; 19 } 20 21 public Size GridSize 22 { 23 get { return (Size)GetValue(GridSizeProperty); } 24 set { SetValue(GridSizeProperty, value); 25 } 26 } 27 28 public static readonly DependencyProperty GridSizeProperty = 29 DependencyProperty.Register("GridSize", typeof(Size), typeof(NewGrid), 30 new PropertyMetadata(new Size())); 31 } 32 33} 34
補足情報(FW/ツールのバージョンなど)
VS 2019
C# XAML
回答1件
あなたの回答
tips
プレビュー