WPF:未调用 IValueConverter

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19453568/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 09:54:03  来源:igfitidea点击:

WPF: IValueConverter not being called

c#wpfbuttonconverter

提问by BrianKE

I am trying to change the 'Background' of a button based on the 'changed' condition of an ObservableCollection. I have an 'IsDirty' boolean property on my ViewModel and I am sure it is getting updated when the ObservableCollection is changed.

我正在尝试根据 ObservableCollection 的“已更改”条件更改按钮的“背景”。我的 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;         
    }
}

回答by Nitin

Remove RelativeSource={RelativeSource Self}, from your binding. This code is making the binding search IsDirty within the Button not in its DataContext.

RelativeSource={RelativeSource Self}从您的绑定中删除, 。此代码使 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");
        }

回答by gleng

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.

您应该在调试项目时检查输出窗口,看看是否有任何绑定错误。

回答by hbarck

It looks like IsDirtydoesn't have change notification. Do you implement INotifyPropertyChangedon the ViewModel? And if it is implemented in ViewModelBase: I can't see any code like this.PropertyChanged(new PropertyChangedEventArgs("IsDirty"));being called when you change IsDirty. So, most probably, the converter isn't called because it doesn't know that IsDirtyhas been changed.

看起来IsDirty没有更改通知。你INotifyPropertyChanged在 ViewModel 上实现了吗?如果它是在 中实现的ViewModelBase:我看不到任何这样的代码。PropertyChanged(new PropertyChangedEventArgs("IsDirty"));当你改变时被调用IsDirty。因此,很可能没有调用转换器,因为它不知道IsDirty已更改。