我创建了一个简单的附加属性,可以在屏幕上拖动项目。
1 /这是你如何在你的元素上实现它:
<Rectangle Fill="Green" local:MyExtension.CanMove="True" />
2 /这就像一个魅力。这样做:
// in resources
<x:Boolean x:Key="MyCanMove">true</x:Boolean>
<Rectangle Fill="Blue" local:MyExtension.CanMove="{StaticResource MyCanMove}" />
3 /但是一种语法不起作用。 此操作失败:
<Rectangle Fill="Red" local:MyExtension.CanMove="{Binding Path=CanMove}" />
有什么不同?唯一不同的是它将值绑定到附加属性,而不是显式或通过静态资源设置它。
我错过了什么。但它是什么?
这是完整的XAML:
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<Grid.DataContext>
<local:ViewModel/>
</Grid.DataContext>
<ToggleSwitch Header="Enable Dragging"
HorizontalAlignment="Center"
IsOn="{Binding CanMove, Mode=TwoWay}">
<ToggleSwitch.RenderTransform>
<TranslateTransform Y="-100" />
</ToggleSwitch.RenderTransform>
</ToggleSwitch>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
<StackPanel.Resources>
<Style TargetType="Rectangle">
<Setter Property="Height" Value="100" />
<Setter Property="Width" Value="100" />
</Style>
<x:Boolean x:Key="MyCanMove">true</x:Boolean>
</StackPanel.Resources>
<Rectangle Fill="Green" local:MyExtension.CanMove="True" />
<Rectangle Fill="Blue" local:MyExtension.CanMove="{StaticResource MyCanMove}" />
<Rectangle Fill="Red" local:MyExtension.CanMove="{Binding Path=CanMove}" />
</StackPanel>
</Grid>
这是完整的代码隐藏:
public class ViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
bool m_CanMove = true;
public bool CanMove
{
get { return m_CanMove; }
set
{
m_CanMove = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("CanMove"));
}
}
}
public class MyExtension
{
// canmove aproperty
public static bool GetCanMove(DependencyObject obj)
{
return (bool)obj.GetValue(CanMoveProperty);
}
public static void SetCanMove(DependencyObject obj, bool value)
{
System.Diagnostics.Debug.WriteLine("SetCanMove");
obj.SetValue(CanMoveProperty, value);
var rectangle = obj as FrameworkElement;
rectangle.ManipulationMode = ManipulationModes.TranslateX | ManipulationModes.TranslateY;
rectangle.ManipulationDelta -= rectangle_ManipulationDelta;
if (value)
rectangle.ManipulationDelta += rectangle_ManipulationDelta;
}
public static readonly DependencyProperty CanMoveProperty =
DependencyProperty.RegisterAttached("CanMove", typeof(bool), typeof(MyExtension), new PropertyMetadata(false));
// implementation
static void rectangle_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
var rectangle = sender as FrameworkElement;
var canMove = System.Convert.ToBoolean(rectangle.GetValue(MyExtension.CanMoveProperty));
if (canMove)
{
var transform = rectangle.RenderTransform as CompositeTransform;
if (transform == null)
rectangle.RenderTransform = (transform = new CompositeTransform());
transform.TranslateX += e.Delta.Translation.X;
transform.TranslateY += e.Delta.Translation.Y;
}
}
}
我会提醒你,这个附加属性在前两个语法中工作正常。结果,我无法想象错误是在附加属性中。而且,我在几个论坛上阅读,其中path=
是绑定到附加属性所必需的,所以我把它包括在内(尽管它没有什么区别)。改变模式(OneWay,TwoWay)并没有什么不同。与ElementName绑定并没有什么区别。我想知道是否在Windows 8.0 WinRT中没有启用它。其他人可以让这个工作吗?
编辑:解决方案
问题是如果没有changed
事件处理程序设置,绑定不会引发已更改的事件。这是更新的MyExtension代码:
public class MyExtension
{
// canmove aproperty
public static bool GetCanMove(DependencyObject obj) { return (bool)obj.GetValue(CanMoveProperty); }
public static void SetCanMove(DependencyObject obj, bool value) { obj.SetValue(CanMoveProperty, value); }
public static readonly DependencyProperty CanMoveProperty =
DependencyProperty.RegisterAttached("CanMove", typeof(bool), typeof(MyExtension), new PropertyMetadata(false, OnCanMoveChanged));
// respond to change
private static void OnCanMoveChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var rectangle = d as FrameworkElement;
rectangle.ManipulationMode = ManipulationModes.TranslateX | ManipulationModes.TranslateY;
rectangle.ManipulationDelta -= rectangle_ManipulationDelta;
if ((bool)e.NewValue)
rectangle.ManipulationDelta += rectangle_ManipulationDelta;
}
// implementation
static void rectangle_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
var rectangle = sender as FrameworkElement;
var canMove = System.Convert.ToBoolean(rectangle.GetValue(MyExtension.CanMoveProperty));
if (canMove)
{
var transform = rectangle.RenderTransform as CompositeTransform;
if (transform == null)
rectangle.RenderTransform = (transform = new CompositeTransform());
transform.TranslateX += e.Delta.Translation.X;
transform.TranslateY += e.Delta.Translation.Y;
}
}
}
答案 0 :(得分:3)
这只是猜测,因为我面前没有编译器,但我想知道绑定基础结构是否不使用您创建的GetCanMove等公开的方法。
尝试在PropertyMetadata
中注册属性更改方法new PropertyMetadata(false, OnCanMoveChanged)
并在那里设置和拆除代码
private void OnCanMoveChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)