Я создал простое прикрепленное свойство, которое позволяет перетаскивать элемент вокруг экрана.Attached.Property = "{Binding}" не работает
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. Может ли кто-нибудь еще заставить это работать?
EDIT: Решение
Проблема заключалась в том, что без установки обработчика в 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;
}
}
}
Спасибо. Так оно и было. –