我试图根据ObservableCollection的“已更改”条件更改按钮的“背景”。我的ViewModel上有一个'IsDirty'布尔属性,并且我确定ObservableCollection更改时,它会得到更新。
但是,按钮的背景并未更改,并且似乎也从未调用过“转换”方法。
我的转换器缺少什么?更改ObservableCollection时,按钮的背景应更改为红色(IsDirty为true)
编辑
我更新了转换器以返回红色或绿色(而不是红色和透明)的值,并且按钮没有背景色,因此可以告诉我转换器从未被调用。
编辑2
添加了显示IsDirty属性的ViewModel代码。
转换器
public class IsDirtyConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return System.Convert.ToBoolean(value) ?
new SolidColorBrush(Colors.Red)
: new SolidColorBrush(Colors.Green);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
视图
<Window x:Class="SerializeObservableCollection.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:conv="clr-namespace:SerializeObservableCollection.Converter"
xmlns:ignore="http://www.ignore.com"
mc:Ignorable="d ignore"
Height="300"
Width="491"
Title="MVVM Light Application"
DataContext="{Binding Main, Source={StaticResource Locator}}">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Skins/MainSkin.xaml" />
</ResourceDictionary.MergedDictionaries>
<conv:IsDirtyConverter x:Key="IsDirtyConverter" />
</ResourceDictionary>
</Window.Resources>
<Grid x:Name="LayoutRoot">
<TextBlock FontSize="36"
FontWeight="Bold"
Foreground="Purple"
Text="{Binding WelcomeTitle}"
VerticalAlignment="Top"
TextWrapping="Wrap" Margin="10,10,10,0" Height="54" HorizontalAlignment="Center" />
<DataGrid Margin="10,69,10,38"
ItemsSource="{Binding CodeCollection, Mode=TwoWay}"/>
<Button Name="SaveButton" Content="Save"
Command="{Binding SaveButtonClickedCommand}"
Background="{Binding
RelativeSource={RelativeSource Self},
Path=IsDirty,
UpdateSourceTrigger=PropertyChanged,
Converter={StaticResource IsDirtyConverter}}"
HorizontalAlignment="Right" Margin="0,0,90,10"
Width="75" Height="20"
VerticalAlignment="Bottom"/>
<Button Content="Refresh" HorizontalAlignment="Right" Margin="0,0,10,10" Width="75"
Command="{Binding RefreshButton_Click}" Height="20" VerticalAlignment="Bottom"/>
</Grid>
</Window>
查看模型
public class MainViewModel : ViewModelBase
{
public bool IsDirty;
/// <summary>
/// ObservableCollection of Codes
/// </summary>
private const string CodeCollectionPropertyName = "CodeCollection";
private ObservableCollection<Code> _codeCollection;
public ObservableCollection<Code> CodeCollection
{
get
{
if (_codeCollection == null)
{
_codeCollection = new ObservableCollection<Code>();
}
return _codeCollection;
}
set
{
if (_codeCollection == value)
{
return;
}
_codeCollection = value;
RaisePropertyChanged(CodeCollectionPropertyName);
}
}
/// <summary>
/// Initializes a new instance of the MainViewModel class.
/// </summary>
public MainViewModel(IDataService dataService)
{
// Load XML file into ObservableCollection
LoadXML();
}
private void LoadXML()
{
try
{
XmlSerializer _serializer = new XmlSerializer(typeof(Codes));
// A file stream is used to read the XML file into the ObservableCollection
using (StreamReader _reader = new StreamReader(@"LocalCodes.xml"))
{
CodeCollection = (_serializer.Deserialize(_reader) as Codes).CodeCollection;
}
// Change notification setup
CodeCollection.CollectionChanged += OnCodeCollectionChanged;
}
catch (Exception ex)
{
// Catch exceptions here
}
}
private void SaveToXML()
{
try
{
XmlSerializer _serializer = new XmlSerializer(typeof(ObservableCollection<Code>));
using (StreamWriter _writer = new StreamWriter(@"LocalCodes.xml"))
{
_serializer.Serialize(_writer, CodeCollection);
}
}
catch (Exception ex)
{
}
}
private RelayCommand _saveButtonClickedCommand;
public RelayCommand SaveButtonClickedCommand
{
get
{
return _saveButtonClickedCommand ??
(_saveButtonClickedCommand = new RelayCommand(
() =>
{
SaveButtonClicked();
}));
}
}
private void SaveButtonClicked()
{
SaveToXML();
}
private void OnCodeCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
IsDirty = true;
}
}
最佳答案
从绑定中删除RelativeSource={RelativeSource Self}
。此代码使Button中的绑定搜索IsDirty不在其DataContext中。
Background="{Binding
Path=IsDirty,
UpdateSourceTrigger=PropertyChanged,
Converter={StaticResource IsDirtyConverter}}"
或使用
Background="{Binding
RelativeSource={RelativeSource Self},
Path=DataContext.IsDirty,
UpdateSourceTrigger=PropertyChanged,
Converter={StaticResource IsDirtyConverter}}"
另外IsDirty应该是属性,而不是变量
private bool _isDirty;
public bool IsDirty
get
{
return _isDirty;
}
set
{
_isDirty = value
_codeCollection = value;
RaisePropertyChanged("IsDirty");
}