今天我发现了一些奇怪的东西(对我而言)。如果我想通过ViewModel中的属性更新DataGrid,Binding将不会收到通知。这里的特殊想法是(我认为)Binding绑定到另一个对象(Collection的一部分)而不是直接改变的属性。
我为您准备了一些示例代码。但首先是一个(Depper)解释。
当然它只是一个示例,但在这里我有一个带有两个公共属性(Items和CurrentItem)的ViewModel。 Items是一个ObservableCollection,用作我的DataGrid的ItemsSource。 CurrentItem是一个String,用作转换器设置背景颜色(对于网格)的指示器。
我将两个实例添加到我的Collection中,并且在程序启动后,行为符合预期。第一行是绿色,第二行是白色(通过转换器和属性设置)。
但是如果我在加载程序后更改了CurrentItem的值(让我们通过按钮说),颜色就不会在我的Datagrid上更新。
如果我在转换器的开头创建一个断点,我可以看到(在加载过程之后)转换器不会再次执行,因此它必须是绑定的问题。我认为问题是我的属性不属于我的Collection中的项目。 OnPropertyChange方法似乎没有正确触发RowStyle的更新。
在现实生活中,集合的模型类不是字符串,模型类实现了INotifyPropertyChange(但我不认为这是问题,因为我只是不更新模型中的任何内容)。
我需要这种行为才能在基于动态指标的情况下突出显示更多行(类似于示例)。如果没有人知道更好的方法,我想我会在我的模型中实现某种属性,并使用ViewModel中的方法更新属性。
视图模型:
public class MainWindowViewModel : INotifyPropertyChanged
{
public static MainWindowViewModel instance = null;
private string _CurrentItem;
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string Property)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(Property));
}
}
public string CurrentItem
{
get
{
return _CurrentItem;
}
set
{
if (value != _CurrentItem)
{
_CurrentItem = value;
OnPropertyChanged("CurrentItem");
OnPropertyChanged("Items");
}
}
}
public ObservableCollection<String> Items { get; set; }
public MainWindowViewModel()
{
instance = this;
Items = new ObservableCollection<string>();
CurrentItem = "First";
Items.Add("First");
Items.Add("Second");
Items.Add("First");
}
查看XAML
<Window.DataContext>
<local:MainWindowViewModel />
</Window.DataContext>
<Window.Resources>
<local:StringToColorConverter x:Key="StringToColorConverter" />
</Window.Resources>
<DockPanel Margin="30">
<Button DockPanel.Dock="bottom" Content="From First to Second" Click="Button_Click" />
<DataGrid IsReadOnly="True" ItemsSource="{Binding Items}" ColumnWidth="*" AutoGenerateColumns="False">
<DataGrid.RowStyle>
<Style TargetType="DataGridRow">
<Setter Property="Background"
Value="{Binding Converter={StaticResource StringToColorConverter}}" />
</Style>
</DataGrid.RowStyle>
<DataGrid.Columns>
<DataGridTextColumn Header="Text" Binding="{Binding}" />
</DataGrid.Columns>
</DataGrid>
</DockPanel>
转换器
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var item = value as string;
if (item == MainWindowViewModel.instance?.CurrentItem)
return "Green";
return "White";
}
很抱歉这篇长篇文章我希望你能理解我的问题,当然也许可以帮助我:)。
答案 0 :(得分:2)
一切都很正常!
这是设计的。 您的背景绑定到DataGrid的第n个对象。 它没有绑定到CurrentItem,因此绑定没有理由更新第n行背景。
因为你有一个ObservableCollection,你可以在 MyItem 类中加上 IsSelected 属性
你应该在 IsSelected 属性上使 MyItem ràise成为PropertyChanged
事件。
当然 MyItem 会实施INotifyPropertyChanged
最后,您应该更改绑定:
<DataGrid.RowStyle>
<Style TargetType="DataGridRow">
<Setter Property="Background"
Value="{Binding Path=IsSelected,
Converter={StaticResource BooleanToColorConverter}}" />
</Style>
</DataGrid.RowStyle>
当然,将StringToColorConverter更改为BooleanToColorConvert将是微不足道的。
此致
答案 1 :(得分:2)
您可以使用IMultiValueConverter
来涉及CurrentItem<DataGrid.RowStyle>
<Style TargetType="DataGridRow">
<Setter Property="Background">
<Setter.Value>
<MultiBinding Converter="{StaticResource MultiStringToColorConverter}">
<Binding />
<Binding Path="DataContext.CurrentItem"
RelativeSource="{RelativeSource FindAncestor,
AncestorType={x:Type Window}}"/>
</MultiBinding>
</Setter.Value>
</Setter>
</Style>
</DataGrid.RowStyle>
转换器
public class MultiStringToColorConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
var item = values[0] as string;
var current = values[1] as string;
if (item == current)
return new SolidColorBrush(Colors.Green);
return new SolidColorBrush(Colors.White);
}
public object[] ConvertBack(object values, Type[] targetType, object parameter,
System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}