I am trying to bind columns and rows of DataGrid
to the same source but DataGrid does not show new value in the ColumnHeader
when I change value in the RowHeader
after TextBox
lost focus. Headers collection contains new values as expected.
xmlns:dataGrid2D="http://gu.se/DataGrid2D"
<Grid>
<DataGrid
dataGrid2D:ItemsSource.RowHeadersSource="{Binding Headers}"
dataGrid2D:ItemsSource.ColumnHeadersSource="{Binding Headers}"
dataGrid2D:ItemsSource.Array2D="{Binding Items}"
IsReadOnly="True"
AutoGenerateColumns="True">
<DataGrid.RowHeaderTemplate>
<DataTemplate>
<TextBox Text="{Binding Value}" />
</DataTemplate>
</DataGrid.RowHeaderTemplate>
</DataGrid>
</Grid>
DataContext:
public class MainViewModel
{
public IEnumerable<Header> Headers { get; } = new Header[]
{ new Header { Value = "1" }, new Header { Value = "2" } };
public string[,] Items { get; } = new string[2, 2] { { "1", "2" }, { "3", "4" } };
}
public class Header
{
public string Value { get; set; }
public override string ToString()
{
return Value;
}
}
What I am doing wrong?
I am changing the Value property from the View side so it does not need INotifyPropertyChanged interface. If I call "Refresh" on DataGrid it updates but with blinking.
Edit:
Why are you downvoting me? Is it a bad question?
Here is one possible solution using the style for DataGridColumnHeader
. I also explicitly used the Value
property instead of the ToString
method.
<Grid>
<DataGrid
dataGrid2D:ItemsSource.RowHeadersSource="{Binding Headers}"
dataGrid2D:ItemsSource.ColumnHeadersSource="{Binding Headers}"
dataGrid2D:ItemsSource.Array2D="{Binding Items}"
IsReadOnly="True"
AutoGenerateColumns="True">
<DataGrid.Resources>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="{Binding Value}"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</DataGrid.Resources>
<DataGrid.RowHeaderTemplate>
<DataTemplate>
<TextBox Text="{Binding Value, UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</DataGrid.RowHeaderTemplate>
</DataGrid>
</Grid>
You need to slightly change the ModelView then:
public class Header: INotifyPropertyChanged
{
private string _Value;
public string Value
{
get
{
return _Value;
}
set
{
_Value = value;
OnPropertyChanged("Value");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}