Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
绑定到ItemSource时WPF自动生成的DataGrid单元格已更改事件_Wpf_Datagrid - Fatal编程技术网

绑定到ItemSource时WPF自动生成的DataGrid单元格已更改事件

绑定到ItemSource时WPF自动生成的DataGrid单元格已更改事件,wpf,datagrid,Wpf,Datagrid,我有一个简单的datagrid,它有自动生成的列,并绑定到一个项目源。此项源每隔一段时间更新一次,我找不到如何为更改的单个单元格触发事件。我想根据数据源的更新是否更改了单元格的先前值来更改单元格的颜色 我也看了,但我仍然不确定如何去实施这一点。一些示例代码将非常有助于在正确的路径上起步。如果您绑定到DataTable,我认为这将不是一条高效的路径。在WPF中,基于绑定到DataTable的DataGrid的内容进行任何类型的样式设置几乎是不可能的。关于StackOverflow有几种建议,但它们

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


我也看了,但我仍然不确定如何去实施这一点。一些示例代码将非常有助于在正确的路径上起步。

如果您绑定到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));
        }
    }
}
公共部分类主窗口:窗口
{
公共主窗口()
{
初始化组件();
this.DataContext=newviewmodel();
}
}
公共类ViewModel:PropertyChangedNotifier
{
公共视图模型()
{
Items=新的ObservableCollection()
{
新的ItemViewModel(){Item1=“Item1FistValue”,Item2=“Item2FirstValue”},
新的ItemViewModel(){Item1=“whocareswhatvalue”,Item2=“IcertillyDont”}
};
//只是为了得到正确的初始状态
foreach(项目中的var项目)
{
item.Item1Changed=false;
}
}
私人可观测收集项目;
公共可观测收集项目
{
得到
{
退货(物品);;
}
设置
{
_项目=价值;
不动产变更(“项目”);
}
}
}
公共类ItemViewModel:PropertyChangedNotifier
{
私有字符串_item1;
私有字符串_item2;
私人住宅项目1变更;
公共布尔项1已更改
{
得到
{
返回-项目1已更改;
}
设置
{
_item1Changed=值;
不动产变更(“项目1变更”);
}
}
公共字符串项1
{
得到
{
返回第1项;
}
设置
{
如果(_item1!=值)
Item1Changed=true;
其他的
Item1Changed=false;
_第1项=价值;
不动产变更(“第1项”);
}
}
公共字符串项2
{
得到
{
返回第2项;
}
设置
{
_第2项=价值;
不动产变更(“第2项”);
}
}
}
公共类PropertyChangedNotifier:INotifyPropertyChanged
{
公共事件属性更改事件处理程序属性更改;
公共void OnPropertyChanged(字符串propertyName)
{
var propertyChanged=propertyChanged;
if(propertyChanged!=null)
{
propertyChanged(这是新的PropertyChangedEventArgs(propertyName));
}
}
}

谢谢你的回答,安德鲁。我是WPF的新手,所以你有一个简短的例子,我可以看看吗?谢谢。另外,我添加了一个简单的演示应用程序——如果它不适合你,请告诉我。