当依赖属性所依赖的变量或字段发生变化时更新依赖属性

发布于 2024-11-24 23:33:35 字数 5021 浏览 1 评论 0原文

我需要做的是?

我需要创建一个表达式,依赖属性应该依赖于该表达式。

假设如下:

Count = dependOne + dependTwo;

这里,Count依赖属性dependOnedependTwo是依赖属性所依赖的两个变量计数 应该取决于。

现在,每当我更改变量 dependOnedependTwo 时,依赖项属性都应该自动更新。

是否可以?如果是的话怎么办?

请参阅下面的代码

XAML:

<Window x:Class="DependecnyProperty.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <TextBox Background="LightGray" Text="{Binding Path=Count}" Height="23" HorizontalAlignment="Left" Margin="164,102,0,0" Name="textBox1" VerticalAlignment="Top" Width="120" />
        <Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="164,148,0,0" Name="button1" VerticalAlignment="Top" Width="120" Click="button1_Click" />
    </Grid>
</Window>

代码隐藏:

namespace DependecnyProperty
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {

        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = this;

            Count = dependOne + dependTwo;
        }

        int dependOne = 0;
        int dependTwo = 0;

        public int Count
        {
            get { return (int)GetValue(CountProperty); }
            set { SetValue(CountProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Count.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty CountProperty =
            DependencyProperty.Register("Count", typeof(int), typeof(MainWindow), new UIPropertyMetadata(12));

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            dependOne = dependOne + 2;
            dependTwo = dependTwo + 1;

            //I need to find way ...now here i have changed value of two variable.
            //now it is possible to change Dependency Property
            //Without here setting the value of dependency property
        }


    }
}

编辑更新的代码隐藏:

namespace DependecnyProperty
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        ViewModel vm;
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = this;

            vm = new ViewModel();
            //this.DataContext = vm;
            Count = vm.DependOne + vm.DependTwo;
        }


        public int Count
        {
            get { return (int)GetValue(CountProperty); }
            set { SetValue(CountProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Count.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty CountProperty =
            DependencyProperty.Register("Count", typeof(int), typeof(MainWindow), new UIPropertyMetadata(12));

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            vm.DependOne++;
            vm.DependTwo++;
            //I need to find way ...now here i have changed value of two variable.
            //now it is possible to change Dependency Property
            //Without here setting the value of dependency property

        }

        public class ViewModel : INotifyPropertyChanged
        {

            public ViewModel()
            {

            }

            private int dependOne;

            public int DependOne
            {
                get
                {
                    return dependOne;
                }
                set 
                { 
                    dependOne = value;
                    OnPropertyChanged("DependOne");
                }
            }

            private int dependTwo;

            public int DependTwo
            {
                get 
                { 
                    return dependTwo; 
                }
                set 
                { 
                    dependTwo = value;
                    OnPropertyChanged("DependTwo");
                }
            }

            #region --  INotifyPropertyChanged Members  --

            public event PropertyChangedEventHandler PropertyChanged;
            public void OnPropertyChanged(string propertyNameArg)
            {
                PropertyChangedEventHandler handler = this.PropertyChanged;

                if (handler != null)
                {
                    handler(this, new PropertyChangedEventArgs(propertyNameArg));
                }
            }
            #endregion
        }
    }
}

What I need to do is?

I need to make one expression on which dependency property should depends on.

Suppose as per below:

Count = dependOne + dependTwo;

Here, Count is Dependency property and dependOne and dependTwo are two variables on which dependency property Count should Depends on.

Now whenever I change variable dependOne or dependTwo the dependency property should have to update automatically.

Is it possible? If yes then how?

See the code below

XAML:

<Window x:Class="DependecnyProperty.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <TextBox Background="LightGray" Text="{Binding Path=Count}" Height="23" HorizontalAlignment="Left" Margin="164,102,0,0" Name="textBox1" VerticalAlignment="Top" Width="120" />
        <Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="164,148,0,0" Name="button1" VerticalAlignment="Top" Width="120" Click="button1_Click" />
    </Grid>
</Window>

CODE BEHIND:

namespace DependecnyProperty
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {

        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = this;

            Count = dependOne + dependTwo;
        }

        int dependOne = 0;
        int dependTwo = 0;

        public int Count
        {
            get { return (int)GetValue(CountProperty); }
            set { SetValue(CountProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Count.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty CountProperty =
            DependencyProperty.Register("Count", typeof(int), typeof(MainWindow), new UIPropertyMetadata(12));

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            dependOne = dependOne + 2;
            dependTwo = dependTwo + 1;

            //I need to find way ...now here i have changed value of two variable.
            //now it is possible to change Dependency Property
            //Without here setting the value of dependency property
        }


    }
}

EDIT UPDATED CODEBEHIND:

namespace DependecnyProperty
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        ViewModel vm;
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = this;

            vm = new ViewModel();
            //this.DataContext = vm;
            Count = vm.DependOne + vm.DependTwo;
        }


        public int Count
        {
            get { return (int)GetValue(CountProperty); }
            set { SetValue(CountProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Count.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty CountProperty =
            DependencyProperty.Register("Count", typeof(int), typeof(MainWindow), new UIPropertyMetadata(12));

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            vm.DependOne++;
            vm.DependTwo++;
            //I need to find way ...now here i have changed value of two variable.
            //now it is possible to change Dependency Property
            //Without here setting the value of dependency property

        }

        public class ViewModel : INotifyPropertyChanged
        {

            public ViewModel()
            {

            }

            private int dependOne;

            public int DependOne
            {
                get
                {
                    return dependOne;
                }
                set 
                { 
                    dependOne = value;
                    OnPropertyChanged("DependOne");
                }
            }

            private int dependTwo;

            public int DependTwo
            {
                get 
                { 
                    return dependTwo; 
                }
                set 
                { 
                    dependTwo = value;
                    OnPropertyChanged("DependTwo");
                }
            }

            #region --  INotifyPropertyChanged Members  --

            public event PropertyChangedEventHandler PropertyChanged;
            public void OnPropertyChanged(string propertyNameArg)
            {
                PropertyChangedEventHandler handler = this.PropertyChanged;

                if (handler != null)
                {
                    handler(this, new PropertyChangedEventArgs(propertyNameArg));
                }
            }
            #endregion
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

苍暮颜 2024-12-01 23:33:35

我不知道什么是最适合您的解决方案。然而,其中之一是您使用以下属性:

    //field
    private int _dependOne;

    //property
    public int DependOne
    {
        get { return _dependOne; }
        set {
            _dependOne = value;
            Count += value;
        }
    }

    //Finally, use the property instead of the field
    //dependOne = dependOne + 2;
    DependOne += 2;

更新:
重要的是您不要在代码隐藏中更新 ViewModel 属性。相反,您可以调用 ViewModel 方法。

XAML

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:Local="clr-namespace:WpfApplication1"
        Title="MainWindow" Height="350" Width="525">

    <StackPanel>
        <StackPanel.Resources>
            <Local:MyConverter x:Key="myConverter"/>
        </StackPanel.Resources>
        <TextBox>
            <TextBox.Text>
                <MultiBinding Converter="{StaticResource myConverter}">
                    <Binding Path="DependOne" Mode="OneWay"/>
                    <Binding Path="DependTwo" Mode="OneWay"/>
                </MultiBinding>
            </TextBox.Text>
        </TextBox>
        <Button Click="button1_Click">click</Button>
    </StackPanel>
</Window>

代码

public partial class MainWindow : Window
{
    ViewModel vm;
    public MainWindow()
    {
        InitializeComponent();

        vm = new ViewModel();
        this.DataContext = vm;
    }


    //public int Count
    //{
    //    get { return (int)GetValue(CountProperty); }
    //    set { SetValue(CountProperty, value); }
    //}

    //// Using a DependencyProperty as the backing store for Count.  This enables animation, styling, binding, etc...
    //public static readonly DependencyProperty CountProperty =
    //    DependencyProperty.Register("Count", typeof(int), typeof(MainWindow), new UIPropertyMetadata(12));

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        vm.UpdateCount();
    }


}

public class ViewModel : INotifyPropertyChanged
{

    public ViewModel()
    {

    }

    private int dependOne = 0;

    public int DependOne
    {
        get
        {
            return dependOne;
        }
        set
        {
            dependOne = value;
            OnPropertyChanged("DependOne");
        }
    }

    private int dependTwo = 0;

    public int DependTwo
    {
        get
        {
            return dependTwo;
        }
        set
        {
            dependTwo = value;
            OnPropertyChanged("DependTwo");
        }
    }

    #region --  INotifyPropertyChanged Members  --

    public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged(string propertyNameArg)
    {
        PropertyChangedEventHandler handler = this.PropertyChanged;

        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyNameArg));
        }
    }
    #endregion

    internal void UpdateCount()
    {
        DependOne = 3;
        DependTwo = 4;
    }
}

public class MyConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        var dependOne = (int)values[0];
        var dependTwo = (int)values[1];

        return (dependOne + dependTwo).ToString();
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}

I don't know what is the best solution for you. One of these ,however, would be that you use Property like:

    //field
    private int _dependOne;

    //property
    public int DependOne
    {
        get { return _dependOne; }
        set {
            _dependOne = value;
            Count += value;
        }
    }

    //Finally, use the property instead of the field
    //dependOne = dependOne + 2;
    DependOne += 2;

UPDATED:
The important thing is that you don't update ViewModel properties in Codebehind. Instead, you could call a ViewModel method.

XAML

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:Local="clr-namespace:WpfApplication1"
        Title="MainWindow" Height="350" Width="525">

    <StackPanel>
        <StackPanel.Resources>
            <Local:MyConverter x:Key="myConverter"/>
        </StackPanel.Resources>
        <TextBox>
            <TextBox.Text>
                <MultiBinding Converter="{StaticResource myConverter}">
                    <Binding Path="DependOne" Mode="OneWay"/>
                    <Binding Path="DependTwo" Mode="OneWay"/>
                </MultiBinding>
            </TextBox.Text>
        </TextBox>
        <Button Click="button1_Click">click</Button>
    </StackPanel>
</Window>

CODE

public partial class MainWindow : Window
{
    ViewModel vm;
    public MainWindow()
    {
        InitializeComponent();

        vm = new ViewModel();
        this.DataContext = vm;
    }


    //public int Count
    //{
    //    get { return (int)GetValue(CountProperty); }
    //    set { SetValue(CountProperty, value); }
    //}

    //// Using a DependencyProperty as the backing store for Count.  This enables animation, styling, binding, etc...
    //public static readonly DependencyProperty CountProperty =
    //    DependencyProperty.Register("Count", typeof(int), typeof(MainWindow), new UIPropertyMetadata(12));

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        vm.UpdateCount();
    }


}

public class ViewModel : INotifyPropertyChanged
{

    public ViewModel()
    {

    }

    private int dependOne = 0;

    public int DependOne
    {
        get
        {
            return dependOne;
        }
        set
        {
            dependOne = value;
            OnPropertyChanged("DependOne");
        }
    }

    private int dependTwo = 0;

    public int DependTwo
    {
        get
        {
            return dependTwo;
        }
        set
        {
            dependTwo = value;
            OnPropertyChanged("DependTwo");
        }
    }

    #region --  INotifyPropertyChanged Members  --

    public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged(string propertyNameArg)
    {
        PropertyChangedEventHandler handler = this.PropertyChanged;

        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyNameArg));
        }
    }
    #endregion

    internal void UpdateCount()
    {
        DependOne = 3;
        DependTwo = 4;
    }
}

public class MyConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        var dependOne = (int)values[0];
        var dependTwo = (int)values[1];

        return (dependOne + dependTwo).ToString();
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}
才能让你更想念 2024-12-01 23:33:35

我会:

  • dependOnedependTwo 放入视图模型中
  • INotifyPropertyChanged 添加到视图模型
  • 调用这些属性的设置器时引发属性更改事件
  • 使用 MultiBinding 绑定依赖项 然后,每当这些属性

更新时,setter 就会自动被调用。

此解决方案的另一个优点是您可以将计数器逻辑与依赖属性逻辑分开。单元测试会更容易,并且可能更容易在不同场景中重用。

I'd:

  • Put dependOne and dependTwo in a View Model
  • Add INotifyPropertyChanged to the View Model
  • Raise the property changed event when those property's setters got called
  • Use a MultiBinding to bind the dependency property to those two view model properties

Then the setter would automatically get called whenever those properties were updated.

Another advantage of this solution is that you could separate the counter logic from the dependency property logic. It would be easier to unit test, and possibly easier to reuse in different scenarios.

伴梦长久 2024-12-01 23:33:35

与 Merlyn Morgan-Graham 的答案非常相似的方法是,您可以在 ViewModel 中引入另一个名为 Count 的只读属性。每当 DependOne 或 DependTwo 更改时引发 PropertyChanged("Count") ,然后您可以针对 Count 进行 OneWay 绑定

private int m_dependOne;
public int DependOne
{
    get { return m_dependOne; }
    set
    {
        m_dependOne = value;
        OnPropertyChanged("DependOne");
        OnPropertyChanged("Count");
    }
}

private int m_dependTwo;
public int DependTwo
{
    get { return m_dependTwo; }
    set
    {
        m_dependTwo = value;
        OnPropertyChanged("DependTwo");
        OnPropertyChanged("Count");
    }
}

public int Count
{
    get
    {
        return m_dependOne + m_dependTwo;
    }
}

然后绑定就像这样简单

<TextBlock Text="{Binding Count, Mode=OneWay}"/>

A pretty similar approach to the answer by Merlyn Morgan-Graham, you can introduce another readonly property called Count in your ViewModel. Raise PropertyChanged("Count") whenever DependOne or DependTwo changes, then you can do a OneWay binding against Count

private int m_dependOne;
public int DependOne
{
    get { return m_dependOne; }
    set
    {
        m_dependOne = value;
        OnPropertyChanged("DependOne");
        OnPropertyChanged("Count");
    }
}

private int m_dependTwo;
public int DependTwo
{
    get { return m_dependTwo; }
    set
    {
        m_dependTwo = value;
        OnPropertyChanged("DependTwo");
        OnPropertyChanged("Count");
    }
}

public int Count
{
    get
    {
        return m_dependOne + m_dependTwo;
    }
}

Then binding is just as simple as

<TextBlock Text="{Binding Count, Mode=OneWay}"/>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文