Reputation:
I use this codes. In this codes, I want to change each row's background color when I click the button. I tried to bind with DataGridRow's background. But I only get BindingExpression.
I know that if I use ObservableCollection as rowdata, it will slove very easy. But I cannot use the collection because I want to bind each column's visibility, too.
I cannot slove to this problem with this code? Please some help.
<StackPanel>
<CheckBox IsChecked="{Binding IsChecked}" Content="I change the header of Column A and I hide Column B." Margin="10"/>
<Button Content="Click!" Click="Button_OnClick" Margin="10" Width="50"/>
<DataGrid IsReadOnly="True"
ItemsSource="{Binding Table}"
AutoGeneratingColumn="DataGrid_OnAutoGeneratingColumn"
x:Name="DataGrid1"
Loaded="DataGrid1_Loaded">
<DataGrid.RowStyle>
<Style TargetType="DataGridRow">
<Setter Property="Background" Value="{Binding MyBackground, Mode=TwoWay}"/>
</Style>
</DataGrid.RowStyle>
</DataGrid>
</StackPanel>
public partial class MainWindow : Window
{
public ViewModel _viewModel = new ViewModel();
public MainWindow()
{
InitializeComponent();
this.DataContext = _viewModel;
}
private void DataGrid_OnAutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
BindingOperations.SetBinding(e.Column,
DataGridColumn.HeaderProperty,
new Binding($"{nameof(ViewModel.ColumnHeader)}[{e.PropertyName}]")
{
Source = _viewModel
});
BindingOperations.SetBinding(e.Column,
DataGridColumn.VisibilityProperty,
new Binding($"{nameof(ViewModel.ColumnVisibility)}[{e.PropertyName}].{nameof(BindableValue_ColumnVisible<Visibility>.Value)}")
{
Source = _viewModel
});
}
private void Button_OnClick(object sender, RoutedEventArgs e)
{
}
int mCount = 0;
string[] displayedColumnOrder;
private void DataGrid1_Loaded(object sender, RoutedEventArgs e)
{
displayedColumnOrder = new string[_viewModel.Table.Columns.Count];
DataGrid _datagrid = (DataGrid)sender;
_getColumnOrder(_datagrid.Columns);
}
void _getColumnOrder(IEnumerable<DataGridColumn> columnCollection)
{
DataGridColumn[] columnArray;
int columnIndexWorking;
displayedColumnOrder = new string[columnCollection.Count()];
columnArray = columnCollection.ToArray();
foreach (var item_Column in columnCollection)
{
columnIndexWorking = item_Column.DisplayIndex;
displayedColumnOrder[columnIndexWorking] = item_Column.Header.ToString();
}
}
}
public class ViewModel : BindableBase
{
private Brush _myBackground = Brushes.AliceBlue;
public Brush MyBackground
{
get
{
return _myBackground;
}
set
{
_myBackground = value;
NotifyPropertyChanged(nameof(MyBackground));
}
}
private bool _isChecked = false;
public bool IsChecked
{
get
{
return _isChecked;
}
set
{
_isChecked = value;
if (value == true)
{
SetHeader();
SetVisible();
}
else
{
UnSetHeader();
UnSetVisible();
}
NotifyPropertyChanged(nameof(IsChecked));
}
}
public DataTable Table { get; } = new DataTable();
public Dictionary<string, string> ColumnHeader { get; } = new Dictionary<string, string>();
public Dictionary<string, BindableValue_ColumnVisible<Visibility>> ColumnVisibility { get; } = new Dictionary<string, BindableValue_ColumnVisible<Visibility>>();
public ViewModel()
{
Table.Columns.Add("A");
Table.Columns.Add("B");
Table.Columns.Add("C");
Table.Columns.Add("D");
Table.Columns.Add("E");
for (int i = 0; i < 10; i++)
{
Table.Rows.Add($"A-{i}", $"B-{i}", $"C-{i}", $"D-{i}", $"E-{i}");
}
foreach (DataColumn column in Table.Columns)
{
ColumnHeader.Add(column.ColumnName, $"Column {column.ColumnName}");
if (column.ColumnName == "B")
{
ColumnVisibility.Add(column.ColumnName, BindableValue_ColumnVisible.Create(Visibility.Collapsed));
}
else
{
ColumnVisibility.Add(column.ColumnName, BindableValue_ColumnVisible.Create(Visibility.Visible));
}
}
}
public void SetHeader()
{
ColumnHeader["A"] = "I changed Column A!!";
NotifyPropertyChanged(nameof(ColumnHeader));
}
public void SetVisible()
{
ColumnVisibility["B"].Value = Visibility.Collapsed;
}
public void UnSetHeader()
{
ColumnHeader["A"] = "Column A";
NotifyPropertyChanged(nameof(ColumnHeader));
}
public void UnSetVisible()
{
ColumnVisibility["B"].Value = Visibility.Visible;
}
}
public class BindableValue_ColumnVisible<T> : BindableBase
{
public T Value
{
get => _value;
set => SetColumnVisibleProperty(ref _value, value);
}
private T _value;
public BindableValue_ColumnVisible()
{
}
public BindableValue_ColumnVisible(T value)
{
Value = value;
}
}
public static class BindableValue_ColumnVisible
{
public static BindableValue_ColumnVisible<T> Create<T>(T value) => new BindableValue_ColumnVisible<T>(value);
}
public class BindableBase : INotifyPropertyChanged
{
protected virtual bool SetColumnVisibleProperty<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
{
return SetColumnVisibleProperty(ref field, value, null, propertyName);
}
protected virtual bool SetColumnVisibleProperty<T>(ref T field, T value, Action onChanged, [CallerMemberName]string propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(field, value)) return false;
field = value;
onChanged?.Invoke();
NotifyPropertyChanged(propertyName);
return true;
}
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
}
Upvotes: 1
Views: 88
Reputation: 169200
If you add a "MyBackground" column to your DataTable
, your current RowStyle
and binding should work:
public ViewModel()
{
Table.Columns.Add("A");
Table.Columns.Add("B");
Table.Columns.Add("C");
Table.Columns.Add("D");
Table.Columns.Add("E");
Table.Columns.Add("MyBackground");
for (int i = 0; i < 10; i++)
{
Table.Rows.Add($"A-{i}", $"B-{i}", $"C-{i}", $"D-{i}", $"E-{i}", "Yellow");
}
...
}
If you set the column to a known string representation of a brush, such as for example "Yellow" or "Red", you don't have to something else. Else, you could use a converter that converts the value in the DataTable
to a Brush
.
By the way, it's pointless to set the Mode
of this Binding
to TwoWay
.
Upvotes: 0
Reputation:
public class MyDataTable : System.Data.DataTable {
private Brush _myBackground = Brushes.AliceBlue;
public Brush MyBackground {
get {
return _myBackground;
}
set {
_myBackground = value;
NotifyPropertyChanged(nameof(MyBackground));
}
}
}
public MyDataTable Table { get; } = new MyDataTable();
<Style TargetType="{x:Type DataGridRow}">
<Setter Property="Background" Value="{Binding MyBackground }" />
</Style>
Upvotes: 0