Attached.Property =" {结合}"不起作用

时间:2013-08-12 20:06:15

标签: windows-8 windows-store-apps winrt-xaml

我创建了一个简单的附加属性,可以在屏幕上拖动项目。

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;
        }
    }
}

1 个答案:

答案 0 :(得分:3)

这只是猜测,因为我面前没有编译器,但我想知道绑定基础结构是否不使用您创建的GetCanMove等公开的方法。

尝试在PropertyMetadata

中注册属性更改方法
new PropertyMetadata(false, OnCanMoveChanged)

并在那里设置和拆除代码

private void OnCanMoveChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)