首页 > 解决方案 > 我可以绑定到每个 DataGridRow 的背景颜色吗?

问题描述

我使用这个代码。在这段代码中,我想在单击按钮时更改每一行的背景颜色。我试图与 DataGridRow 的背景绑定。但我只得到 BindingExpression。

我知道如果我使用 ObservableCollection 作为行数据,它会很容易解决。但我不能使用该集合,因为我也想绑定每一列的可见性。

我不能用这段代码解决这个问题?请帮忙。

    <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));
            }
        }
    }

标签: c#wpf

解决方案


如果您将“MyBackground”列添加到您的DataTable,您的当前RowStyle和绑定应该可以工作:

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");
    }
...
}

如果将列设置为画笔的已知字符串表示形式,例如“黄色”或“红色”,则不必设置其他内容。否则,您可以使用将 中的值转换为a的转换器DataTableBrush

顺便说一句,将Modethis设置为 是没有意义BindingTwoWay


推荐阅读