WPF: IValueConverter nicht genannt
Ich versuche, ändern Sie die 'Hintergrund' - eine Schaltfläche auf der Grundlage der 'geänderten Zustand einer ObservableCollection. Ich habe ein 'IsDirty -' boolean-Eigenschaft auf meinem ViewModel und ich bin sicher, es wird immer aktualisiert, wenn sich die ObservableCollection ist geändert.
Jedoch der hintergrund der Schaltfläche wird nicht geändert und es scheint nicht, dass die "Convert" - Methode wird immer aufgerufen wird.
Was bin ich mit meinem converter? Der button-hintergrund sollte rot ändern, wenn der ObservableCollection geändert wird (IsDirty ist wahr)
BEARBEITEN
Ich aktualisiert der Konverter, um einen Wert zurückzugeben, der rot oder grün (statt rot und transparent) und die Taste hat keine Hintergrundfarbe, so dass mir der Konverter ist nie genannt.
EDIT 2
Hinzugefügt, die ViewModel-code zeigt die IsDirty-Eigenschaft.
Konverter
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();
}
}
Ansicht
<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-Modell
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;
}
}
- Keine verbindlichen Fehler in der debug-Ausgabe?
- Keine, die ich finden kann
Du musst angemeldet sein, um einen Kommentar abzugeben.
Entfernen
RelativeSource={RelativeSource Self}
aus Ihrer Bindung. Dieser code macht die Bindung Suche IsDirty innerhalb der Schaltfläche nicht in seiner DataContext.ODER verwenden Sie
Auch IsDirty sollte sein Eigentum nicht variabel
Ich glaube nicht, dass Sie verbindlich sind Sie richtig. Versuchen Sie dies:
Sollten Sie überprüfen Sie die Ausgabe-Fenster, wenn Sie das Projekt Debuggen, um zu sehen, wenn Sie keine verbindliche Fehler.
Sieht es aus wie
IsDirty
nicht ändern Benachrichtigung. Setzen SieINotifyPropertyChanged
im ViewModel? Und wenn es umgesetzt wird inViewModelBase
: ich sehe keinen code.PropertyChanged(new PropertyChangedEventArgs("IsDirty"));
wird aufgerufen, wenn Sie ändernIsDirty
. So, wahrscheinlich ist der Konverter nicht genannt, weil Sie nicht wissen, dassIsDirty
geändert wurde.