gpt4 book ai didi

c# - INotifyPropertyChanged 绑定(bind)未按预期更新

转载 作者:行者123 更新时间:2023-12-03 10:30:07 25 4
gpt4 key购买 nike

所以这是我正在努力解决的问题:我有一个自定义用户控件,它公开了两个绑定(bind)到我的 ViewModel 的依赖项属性。在我的 ViewModel 中,我有一个类的实例,它包含多个属性,这些属性表示与用户控件以及控件操作的项目相关的值。这里有一些示例代码可以直观地解释它,所以这里是我的控件的一个简单示例,它是一个与允许用户锁定 slider 的复选框相结合的 slider 。

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

IsLocked 和 SliderValue 是有效操作自定义控件中包含的复选框和 slider 的依赖项属性。除了与我定义的类的绑定(bind)之外,所有控制功能都按预期工作。如果我创建单个属性,例如在一个 int 属性和一个 bool 属性中,绑定(bind)将按预期工作。但是我有五个 slider ,实际代码中的每个 slider 都有五个与之相关的属性。我试图通过创建一个类来将这些属性保存在可重用对象中来消除代码重复,从而将我的 25 个属性缩减为 5 个类实例。

我的 CustomClass 继承 ObservableObject 并具有分别名为 IsLocked 和 SliderValue 的 bool 属性和 int 属性。对于更多视觉辅助,这里是它的样子:
    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 );
}
}

为什么绑定(bind)到类中属性的依赖属性的更新不能正确更新?是因为您不能自行正确更新类实例属性,而是在发生更改时必须更新整个类实例?还是我需要进一步自定义此 ViewModel 属性中的 setter ?因为它现在更改 slider 值或复选框根本不会触及绑定(bind)属性,并且在调试时没有任何错误。

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

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

任何帮助将不胜感激。

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

在属性绑定(bind)中使用类并不难。我必须错过一些补救措施。

最佳答案

这是一个完整的例子:

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));

}
}

现在的xml:
<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>

关于c# - INotifyPropertyChanged 绑定(bind)未按预期更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7899094/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com