INotifyPropertyChanged绑定未按预期更新

本文关键字:更新 绑定 INotifyPropertyChanged | 更新日期: 2023-09-27 18:12:38

所以这里是我头痛的问题:我有一个自定义用户控件,它暴露了绑定到我的ViewModel的两个依赖属性。在我的ViewModel中,我有一个类的实例,它包含多个属性,这些属性表示与用户控件以及控件操作的项相关的值。这里有一些示例代码来直观地解释它这里是我的控件的一个简单示例,它是一个滑动条,它与一个复选框相结合,允许用户锁定滑动条。

    <custom:SliderControl IsLocked="{Binding Path=CustomClass.IsLocked, Mode=TwoWay}" SliderValue="{Binding Path=CustomClass.Value, Mode=TwoWay}" />

IsLocked和SliderValue是依赖属性,它们有效地操作自定义控件中包含的复选框和滑动条。除了到我定义的类的绑定之外,所有控制函数都按预期工作。如果我创建单独的属性,比如一个int属性和一个bool属性,绑定就会按预期工作。但是我有5个滑块,每个滑块在我的实际代码中都有5个属性。我试图通过创建一个类来在可重用对象中保存这些属性来消除代码重复,将我的25个属性减少到5个类实例。

我的CustomClass继承了ObservableObject,并有一个bool属性和一个int属性,分别名为IsLocked和SliderValue。这里是更多的视觉辅助:

    public class CustomClass : ObservableObject
    {
        public const string SliderValuePropertyName = "SliderValue";
        private int _sliderValue= 0;
        public int SliderValue
        {
            get
            {
                return _sliderValue;
            }
            set
            {
                if (_sliderValue== value)
                {
                    return;
                }

                _sliderValue= value;
                RaisePropertyChanged(SliderValuePropertyName );
            }
        }
    public const string IsCheckedPropertyName = "IsChecked";
    private bool _isChecked = false;
    public bool IsChecked
    {
        get
        {
            return _isChecked;
        }
        set
        {
            if (_isChecked == value)
            {
                return;
            }
            _isChecked = value;
            RaisePropertyChanged(IsCheckedPropertyName);
        }
    }

ViewModel属性非常相似,看起来像这样,当ViewModel加载时创建了一个类的新实例:

    public const string SliderOnePropertyName = "SliderOne";
    private CustomClass _sliderOne;
    public CustomClass SliderOne
    {
        get
        {
            return _sliderOne;
        }
        set
        {
            if (_sliderOne== value)
            {
                return;
            }
            _sliderOne= value;
            RaisePropertyChanged(SliderOnePropertyName );
        }
    }

为什么在类中绑定到属性的依赖属性的更新不能正确更新?是因为你不能正确地更新类实例属性本身,而是必须更新整个类实例每当发生变化?或者我需要在这个ViewModel属性中进一步自定义setter吗?现在,改变滑动条值或复选框根本不会触及绑定属性,并且在调试时不会出现任何错误。

编辑:我还将控件包围在Border中,并将Border元素的DataContext设置为类的DataContext,然后将更简单的路径绑定应用于底层自定义控件。然而,这对我的问题没有任何影响。

我是一个土生土长的程序员,所以当我把代码放在一起的时候,我经常会错过一些东西,我猜这就是这种情况,除非我正在尝试的东西不能工作。

任何帮助都将是非常感激的。

编辑:所以我一直在玩弄一个自定义事件,它会让我知道何时自定义控件的特定属性发生变化,然后在我的ViewModel中连接该事件以更新现有的类。这可以工作,但仍然会创建代码重复,因为现在我必须有10个事件,每个控件2个事件,一个检查滑动条的值何时改变,另一个检测复选框的IsChecked值何时改变。由于无法路由多个命令参数(例如操纵滑块的简单字符串标识符以及希望在代码中使用的值),因此存在这种代码重复。这个限制意味着我不能仅仅使用两个事件来区分在定义的方法中哪个控件正在发生变化,因为将物理控件暴露给ViewModel会破坏MVVM模式。使用类作为用户控件的数据上下文,这样我就不关心正在操作的控件是什么,因为它们每个都有自己的类实例。使用事件可以解开MVVM模式,因为现在我需要知道用户正在操作五个控件中的哪个。

在属性绑定中使用类不会这么难。

INotifyPropertyChanged绑定未按预期更新

下面是一个完整的例子:

public partial class MainPage : UserControl
{
    public MainPage()
    {
        InitializeComponent();
        this.DataContext = new ViewModel();
    }
}

public class ViewModel
{
    public SliderValues slv { get; private set; }
    public ViewModel()
    {
        slv = new SliderValues();
    }
}
public class SliderValues : INotifyPropertyChanged
{
    bool _isLocked = false;
    public bool IsLocked
    {
        get { return _isLocked; }
        set
        {
            _isLocked = value;
            OnPropertyChanged("IsLocked");
        }
    }
    int _theValue = 5;
    public int TheValue
    {
        get { return _theValue; }
        set
        {
            _theValue = value;
            OnPropertyChanged("TheValue");
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string prop)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(prop));
    }
}

现在xaml:

<UserControl x:Class="TestBindings.MainPage"
    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"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">
    <Grid x:Name="LayoutRoot" Background="White">
        <Slider Height="23" HorizontalAlignment="Left" Margin="114,138,0,0" Name="slider1" VerticalAlignment="Top" Width="100"
                DataContext="{Binding slv}" Value="{Binding TheValue, Mode=TwoWay}"/>
    </Grid>
</UserControl>

可能只是语法错误。试试这个

{= CustomClass绑定路径。IsLocked模式= TwoWay}

试试这个…<custom:SliderControl DataContext="{Binding CustomClass}" IsLocked="{Binding IsLocked, Mode=TwoWay}" SliderValue="{Binding Value, Mode=TwoWay}" />