如何更新Canvas附加属性还会更新绑定视图模型属性?

时间:2014-01-04 15:07:24

标签: c# wpf xaml

我通过在代码隐藏中使用静态Canvas.SetTop方法来改变WPF Canvas中UIElement的位置(在完整的应用程序中我使用的是复杂的Rx链但是对于这个例子我'将其简化为按钮单击)。

我遇到的问题是XAML中附加属性Canvas.Top的值绑定到我的ViewModel中的属性。调用Canvas.SetTop会绕过我的ViewModel中的set,因此我没有获得更新的值。如何更新代码隐藏中的Canvas.Top值,以便调用ViewModel属性的setter?

XAML查看:

<Window x:Class="WpfApplication1.MainWindowView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="300" Width="300">
    <Grid>
        <Canvas>
            <Button Content="Move Button" Canvas.Top="{Binding ButtonTop}" Click="ButtonBase_OnClick" />
        </Canvas>
    </Grid>
</Window>

代码隐藏:

using System.Windows;
using System.Windows.Controls;

namespace WpfApplication1
{
    public partial class MainWindowView : Window
    {
        public MainWindowView()
        {
            InitializeComponent();
            this.DataContext = new MainWindowViewModel();
        }

        private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
        {
            Canvas.SetTop((UIElement) sender, Canvas.GetTop((UIElement) sender) + 5);
        }
    }
}

视图模型:

using System.Windows;

namespace WpfApplication1
{
    public class MainWindowViewModel : DependencyObject
    {
        public static readonly DependencyProperty ButtonTopProperty = DependencyProperty.
            Register("ButtonTop", typeof(int), typeof(MainWindowViewModel));

        public int ButtonTop
        {
            get { return (int) GetValue(ButtonTopProperty); }
            set { SetValue(ButtonTopProperty, value); }
        }

        public MainWindowViewModel()
        {
            ButtonTop = 15;
        }
    }
}

1 个答案:

答案 0 :(得分:1)

首先,你需要Binding Mode设置为TwoWay

<Button Content="Move Button" Canvas.Top="{Binding ButtonTop, Mode=TwoWay}"
        Click="ButtonBase_OnClick" />

此外,如果您从后面的代码设置它,请使用SetCurrentValue()方法设置,否则绑定将被破坏,ViewModel实例将不会更新

UIElement uiElement = (UIElement)sender;
uiElement.SetCurrentValue(Canvas.TopProperty, Canvas.GetTop(uiElement) + 5);

与提到的here一样,不要在DP的包装属性中编写代码:

  

WPF绑定引擎直接调用GetValueSetValue(绕过   财产制定者和吸气者)。

如果您需要同步属性更改,请创建 PropertyChangedCallback 并在那里进行同步:

public static readonly DependencyProperty ButtonTopProperty = DependencyProperty.
        Register("ButtonTop", typeof(int), typeof(MainWindowViewModel),
                    new UIPropertyMetadata(ButtonTopPropertyChanged));

    private static void ButtonTopPropertyChanged(DependencyObject sender,
                                         DependencyPropertyChangedEventArgs args)
    {
        // Write synchronization logic here
    }

否则只有正常的CLR属性,您应该考虑在您的课程上实施INotifyPropertyChanged

private double buttonTop;
public double ButtonTop
{
   get { return buttonTop; }
   set
   {
      if(buttonTop != value)
      {
         // Synchronize here
         buttonTop = value;
      }
   }
}
相关问题