[英]WPF: IValueConverter not being called
I am trying to change the 'Background' of a button based on the 'changed' condition of an ObservableCollection. 我试图根据ObservableCollection的“已更改”条件更改按钮的“背景”。 I have an 'IsDirty' boolean property on my ViewModel and I am sure it is getting updated when the ObservableCollection is changed.
我的ViewModel上有一个'IsDirty'布尔属性,我确信它会在更改ObservableCollection时更新。
However, the background of the button is not being changed and it doesn't appear that the 'Convert' method is ever being called. 但是,按钮的背景没有被更改,并且似乎没有调用'Convert'方法。
What am I missing with my converter? 我的转换器缺少什么? The button's background should change to red when the ObservableCollection is changed (IsDirty is true)
更改ObservableCollection时,按钮的背景应更改为红色(IsDirty为true)
EDIT 编辑
I updated the converter to return a value of red or green (instead of red and transparent) and the button has no background color so that would tell me the converter is never getting called. 我更新了转换器以返回红色或绿色(而不是红色和透明)的值,按钮没有背景颜色,这样就可以告诉我转换器永远不会被调用。
EDIT 2 编辑2
Added the ViewModel code showing the IsDirty property. 添加了显示IsDirty属性的ViewModel代码。
Converter 变流器
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();
}
}
View 视图
<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>
View Model 查看模型
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;
}
}
Remove RelativeSource={RelativeSource Self}
, from your binding. 从绑定中删除
RelativeSource={RelativeSource Self}
。 This code is making the binding search IsDirty within the Button not in its DataContext. 此代码使得Button内的绑定搜索IsDirty不在其DataContext中。
Background="{Binding
Path=IsDirty,
UpdateSourceTrigger=PropertyChanged,
Converter={StaticResource IsDirtyConverter}}"
OR use 或使用
Background="{Binding
RelativeSource={RelativeSource Self},
Path=DataContext.IsDirty,
UpdateSourceTrigger=PropertyChanged,
Converter={StaticResource IsDirtyConverter}}"
Also IsDirty should be property not variable IsDirty也应该是属性不可变的
private bool _isDirty;
public bool IsDirty
get
{
return _isDirty;
}
set
{
_isDirty = value
_codeCollection = value;
RaisePropertyChanged("IsDirty");
}
I don't think you are binding this correctly. 我认为你没有正确地约束这个。 Try this:
试试这个:
Background="{Binding IsDirty, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource IsDirtyConverter}}"
You should check the output window when you are debugging the project to see if you get any binding errors. 在调试项目时应检查输出窗口,以查看是否出现任何绑定错误。
It looks like IsDirty
doesn't have change notification. 看起来
IsDirty
没有更改通知。 Do you implement INotifyPropertyChanged
on the ViewModel? 你在ViewModel上实现了
INotifyPropertyChanged
吗? And if it is implemented in ViewModelBase
: I can't see any code like this. 如果它是在
ViewModelBase
实现的:我看不到像这样的代码。 PropertyChanged(new PropertyChangedEventArgs("IsDirty"));
being called when you change IsDirty
. 当你改变
IsDirty
时被调用。 So, most probably, the converter isn't called because it doesn't know that IsDirty
has been changed. 因此,最有可能的是,转换器未被调用,因为它不知道
IsDirty
已被更改。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.