【问题标题】:WPF Autogenerated DataGrid Cell changed event when bound to ItemSource绑定到 ItemSource 时 WPF 自动生成的 DataGrid Cell 更改事件
【发布时间】:2013-08-14 05:43:29
【问题描述】:

我有一个简单的数据网格,它具有自动生成的列并绑定到项目源。此项目源会定期更新,我找不到如何为单个单元格更改触发事件。我想根据对数据源的更新是否更改了单元格的先前值来更改单元格的颜色。

我查看了Highlighting cells in WPF DataGrid when the bound value changeshttp://codefornothing.wordpress.com/2009/01/25/the-wpf-datagrid-and-me/,但我仍然不确定如何实现这一点。一些示例代码对于开始正确的道路非常有帮助。

【问题讨论】:

    标签: wpf datagrid


    【解决方案1】:

    如果您要绑定到 DataTable,我认为这不会是一条有效的路径。在 WPF 中几乎不可能基于 DataTable 绑定的 DataGrid 的内容进行任何类型的样式设置。关于 StackOverflow 有几个建议,但它们通常非常老套、事件驱动(这在 WPF 中通常是坏消息),并且是维护的噩梦。

    但是,如果您要绑定的 ItemsSource 是 ObservableCollection,其中 RowViewModel 是表示 DataGrid 单行中数据的类,那么它应该不会太糟糕。确保 RowViewModel 实现 INotifyPropertyChanged,并简单地使用更新后的数据更新各个 RowViewModel。然后,您可以添加逻辑以在 RowViewModel 上公开一个附加属性,该属性指示特定值是否为新值 - 只需使用 XAML 中的一些样式/触发器来根据此新属性的值设置背景颜色。

    这是后者的一个示例:如果您编辑第一列中的一个值,它将使单元格变为红色。如果您通过数据库更新以编程方式更改 ItemViewModel 中的值,也会发生同样的事情。

    XAML:

    <Window x:Class="ShowGridUpdates.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <DataGrid ItemsSource="{Binding Items}" AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding Item1, UpdateSourceTrigger=PropertyChanged}">
                    <DataGridTextColumn.CellStyle>
                        <Style TargetType="DataGridCell">
                            <Style.Setters>
                                <Setter Property="Background" Value="Blue"/>
                                <Setter Property="Foreground" Value="White"/>
                            </Style.Setters>
                            <Style.Triggers>
                                <DataTrigger Binding="{Binding Item1Changed}" Value="True">
                                    <Setter Property="Background" Value="Red"/>
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </DataGridTextColumn.CellStyle>
                </DataGridTextColumn>
                <DataGridTextColumn Binding="{Binding Item2}"/>
            </DataGrid.Columns>
        </DataGrid>   
    </Grid>
    

    背后的代码:

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new ViewModel();
        }
    }
    
    public class ViewModel : PropertyChangedNotifier
    {
        public ViewModel()
        {
            Items = new ObservableCollection<ItemViewModel>()
            {
                new ItemViewModel(){Item1="Item1FistValue", Item2="Item2FirstValue"},
                new ItemViewModel(){Item1="whocareswhatvalue", Item2="Icertainlydont"}
            };
    
            //just to get the initial state correct
            foreach (var item in Items)
            {
                item.Item1Changed = false;
            }
        }
    
        private ObservableCollection<ItemViewModel> _items;
    
        public ObservableCollection<ItemViewModel> Items
        {
            get
            {
                return _items;
            }
            set
            {
                _items = value;
                OnPropertyChanged("Items");
            }
        }
    }
    
    public class ItemViewModel : PropertyChangedNotifier
    {
        private string _item1;
        private string _item2;
    
        private bool _item1Changed;
    
        public bool Item1Changed
        {
            get
            {
                return _item1Changed;
            }
            set
            {
                _item1Changed = value;
                OnPropertyChanged("Item1Changed");
            }
        }
    
        public string Item1
        {
            get
            {
                return _item1;
            }
            set
            {
                if (_item1 != value)
                    Item1Changed = true;
                else
                    Item1Changed = false;
    
                _item1 = value;
                OnPropertyChanged("Item1");
            }
        }
    
        public string Item2
        {
            get
            {
                return _item2;
            }
            set
            {
                _item2 = value;
                OnPropertyChanged("Item2");
            }
        }
    }
    
    public class PropertyChangedNotifier : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged(string propertyName)
        {
            var propertyChanged = PropertyChanged;
            if (propertyChanged != null)
            {
                propertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
    

    【讨论】:

    • 感谢安德鲁的回答。我对 WPF 很陌生,所以你有一个简短的例子,我可以看看吗?谢谢
    • 在那里,我添加了一个简单的演示应用程序 - 如果它不适合您,请告诉我。
    猜你喜欢
    • 1970-01-01
    • 2012-11-13
    • 1970-01-01
    • 2011-03-26
    • 1970-01-01
    • 1970-01-01
    • 2018-12-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多