从XAML页面绑定后的代码中获取或设置INotifyPropertyChanged类的属性值

本文关键字:设置 INotifyPropertyChanged 属性 获取 代码 XAML 绑定 | 更新日期: 2023-09-27 18:12:38

我已经将组框绑定到INotifyPropertyChanged类。

页面资源

    <Page.Resources>
       <current:UserAccountsStatusHandler x:Key="UserAccounts" />
    </Page.Resources>
<<p> 组框/strong>
<GroupBox
                Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="2"
                Header="Select Action:"
                Foreground="{DynamicResource DynamicFrmFG}"
                VerticalAlignment="Stretch" HorizontalAlignment="Left"
                Height="50"
                DataContext="{StaticResource ResourceKey=UserAccounts}">
                <StackPanel 
                    Orientation="Horizontal"
                    HorizontalAlignment="Stretch" VerticalAlignment="Center"
                    Height="Auto">
                    <RadioButton
                        Content="Insert" 
                        Foreground="{DynamicResource DynamicFrmFG}" Height="16"
                        IsChecked="{Binding Path=UserAccountAction, Converter={StaticResource enumToBooleanConverter}, 
                                  ConverterParameter={x:Static enums:UserAccountActions.Insert}, UpdateSourceTrigger=PropertyChanged}"
                        Margin="0,0,10,0" 
                        Click="RadioButton_Click" />
                    <RadioButton
                        Content="Update" 
                        Foreground="{DynamicResource DynamicFrmFG}" Height="16"
                        IsChecked="{Binding Path=UserAccountAction, Converter={StaticResource enumToBooleanConverter}, 
                                  ConverterParameter={x:Static enums:UserAccountActions.Update}, UpdateSourceTrigger=PropertyChanged}"
                        Margin="0,0,10,0" 
                        Click="RadioButton_Click" />
                    <RadioButton
                        Content="Delete" 
                        Foreground="{DynamicResource DynamicFrmFG}" Height="16"
                        IsChecked="{Binding Path=UserAccountAction, Converter={StaticResource enumToBooleanConverter}, 
                                  ConverterParameter={x:Static enums:UserAccountActions.Delete}, UpdateSourceTrigger=PropertyChanged}"
                        Margin="0,0,10,0" 
                        Click="RadioButton_Click" />
                </StackPanel>
            </GroupBox>

public class UserAccountsStatusHandler : INotifyPropertyChanged
{
    private UserAccountActions userAccountAction;
    public UserAccountActions UserAccountAction 
    {
        get { return userAccountAction; } 
        set 
        {
            userAccountAction = value;
            IsSaveEnabled = (userAccountAction == UserAccountActions.None) ? false : true;
            OnPropertyChanged("UserAccountAction"); 
        } 
    }
    private bool isSavedEnabled;
    public bool IsSaveEnabled { get { return isSavedEnabled; } set { isSavedEnabled = value; OnPropertyChanged("IsSaveEnabled"); } }
    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

这一切都工作如预期。我单击其中一个单选按钮,属性就改变了,保存按钮就启用了。然而,我试图弄清楚我如何从类中拉出这些值,在页面后面的代码中,而实际上不必从UI中拉出组框的DataContext,然后调用类。

如果我尝试在页面后面的代码中创建类的新实例,如预期的那样,我得到默认值。到目前为止,我发现如何获取/设置值的唯一方法是将变量的值设置为等于组框数据上下文,如下所示:

        var test = (UserAccountsStatusHandler)tempGroupBoxName.DataContext;
        test.IsSaveEnabled = false;

我读过的很多东西都说数据层不应该知道任何关于UI的事情。所以我不知道该怎么做。如有任何帮助,我将不胜感激。

编辑:添加我以前做的我认为是错误的也

private UserAccountsStatusHandler mainStatusHandler;
mainStatusHandler = new UserAccountsStatusHandler();               
base.DataContext = mainStatusHandler;
在这一点上,我可以很容易地调用mainStatusHandler来获取像IsSavedEnabled这样的东西,并确定用户从UserAccountAction中选择了什么动作。我使用IsSavedEnabled的唯一真正原因是禁用按钮时,标签重新加载页面。确保他们不会在没有实际选择一个操作之前点击保存按钮,然后启用保存按钮。然后他们必须点击Save按钮来执行后面的代码以将数据保存到服务器。

从XAML页面绑定后的代码中获取或设置INotifyPropertyChanged类的属性值

由于您只是将其用于某种形式的验证,因此您确实需要使用iccommand实现。因此,在本例中,修改视图模型以实现iccommand接口以及INotifyPropertyChanged。

public class UserAccountsStatusHandler : INotifyPropertyChanged, ICommand
{
    private UserAccountActions userAccountAction;
    public UserAccountActions UserAccountAction
    {
        get { return userAccountAction; }
        set
        {
            userAccountAction = value;
            IsSaveEnabled = (userAccountAction == UserAccountActions.None) ? false : true;
            OnPropertyChanged("UserAccountAction");
            // Refresh the CanExecute method.
            OnCanExecuteChanged();
        }
    }
    private bool isSavedEnabled;
    public bool IsSaveEnabled { get { return isSavedEnabled; } set { isSavedEnabled = value; OnPropertyChanged("IsSaveEnabled"); } }
    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
    public bool CanExecute(object parameter)
    {
        return userAccountAction.SomeActionSelected != null;
    }
    public event EventHandler CanExecuteChanged;
    private void OnCanExecuteChanged()
    {
        if (this.CanExecuteChanged!= null)
            this.CanExecuteChanged(this, new EventArgs());
    }
    public void Execute(object parameter)
    {
        // perform save code.
    }
}

现在在您的XAML中,如果您的组框有UserAccountStatusHandler作为它的数据上下文,您可以使用分配您的组框名称,并将您的按钮绑定到它。

<GroupBox x:Name="UserAccountStatusGroupBox"></GroupBox>
<Button Content="Save"
        Command={Binding ElementName=UserAccountStatusGroupBox, Path=DataContext} />

当视图被加载时,按钮调用CanExecute。如果返回值为false,按钮将自动禁用。如果为true,则启用该功能。当视图模型中的属性被更改时,然后调用CanExecuteChanged处理程序,它将重新评估保存按钮是否可以启用。

一般来说,每个视图/用户控件应该有一个视图模型。在这种情况下,视图(窗口/页面)应该将视图模型作为其数据上下文,而不是GroupBox。这是最佳实践。

我建议您仔细阅读与MVVM一起工作的命令模式。对于这样的事情,应该没有任何代码隐藏。它应该全部包含在视图模型中。视图模型的目的是支持视图

一般来说,您创建的每个视图都应该有一个ViewModel:

<Page.DataContext>
     <local:MyViewModel/>
</Page.DataContext>

您的UserAccountsStatusHandler可以是您的ViewModel在这种情况下。但是通过将它设置在Page级别作为DataContext,您就不需要太担心从后面的代码中挖掘UI了。

你可以像这样在CodeBehind中公开一个属性:

private MyViewModel ViewModel 
{
    get 
    { 
        return DataContext as MyViewModel;
    }
}

现在你可以直接使用:

MyViewModel.IsSaveEnabled = false;

哪个更好。

但是,我会避免在代码隐藏中放入太多逻辑。我更喜欢让你的按钮调用ViewModel上的Save()方法,然后让ViewModel相应地更新自己。

通常我不设置控件的DataContext在我的页面/窗口,而是设置根对象本身的数据上下文。我还添加了一个私有属性,以便在必要时易于使用(它只是返回DataContext的值转换到我的视图模型的类)。

然后你只需要使用这个属性,这将使你能够访问绑定到UI的值