我通过在代码隐藏中使用静态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;
}
}
}
答案 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绑定引擎直接调用
GetValue
和SetValue
(绕过 财产制定者和吸气者)。
如果您需要同步属性更改,请创建 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;
}
}
}