Grid.Row 和类似属性如何获得如此出色的 DESIGN TIME 支持?
How do Grid.Row and similar properties get such great DESIGN TIME support?
问题:
Grid.Row、Grid.Column、Canvas.SetTop 等属性本身具有强大的 DesignTime 支持。您将它们附加到子元素,并观察 xaml 更新。它们的实现与我下面的示例有何不同?
示例:
在这个例子中,我创建了一个名为 position 的 attached 属性。我可以将 position 属性 附加到网格中的任何子元素。这样做会更新他们的行和列。
public static void SetPosition(DependencyObject obj, Positioning value) => obj.SetValue(PositionProperty, value);
public static void GetPosition(DependencyObject obj) => (Positioning)obj.GetValue(PositionProperty);
public static readonly DependencyProperty PositionProperty = DependencyProperty.RegisterAttatched( "Position", typeof(Positioning),
new PropertyMetadata( Positioning.Normal, OnPositionChanged));
public static void OnPositionChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
UIElement item = obj as UIElement;
if(item == null)
return;
switch((Positioning) e.NewValue)
{
case Positioning.Middle:
Grid.SetRow(item, 4);
Grid.SetColumn(item, 2);
break;
default:
Grid.SetRow(item, 0);
Grid.SetColumn(item, 0);
}
}
//Usage:
<Rectangle local:Position="Middle" Fill="Pink" Height="40" Width="40"/>
这在运行时间有效,但在设计时间无效。我最好的猜测是在设计时可能没有调用 OnPositionChanged?
我尝试过的事情:
- 当属性改变时调用一个函数(见上面的例子)
- 添加 FrameworkPropertyMetadataOptions.AffectsRender
等属性
- 覆盖 ItemsControl 的 OnItemsChanged() 函数
我不知道你把你的声明放在哪里了,但以下是有效的:
window:
<Window
x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfApp1"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<local:UserControl1 local:UserControl1.Position="Zero" Background="Red" />
</Grid>
</Window>
控件:
using System.Windows;
using System.Windows.Controls;
namespace WpfApp1
{
public partial class UserControl1
{
public static readonly DependencyProperty PositionProperty = DependencyProperty.RegisterAttached(
"Position", typeof(Position), typeof(UserControl1),
new PropertyMetadata(default(Position), PositionPropertyChangedCallback));
public UserControl1()
{
InitializeComponent();
}
private static void PositionPropertyChangedCallback(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
if (!(o is UIElement uiElement))
return;
var position = (Position) e.NewValue;
var value = (int) position;
Grid.SetRow(uiElement, value);
}
public static void SetPosition(DependencyObject element, Position value)
{
element.SetValue(PositionProperty, value);
}
public static Position GetPosition(DependencyObject element)
{
return (Position) element.GetValue(PositionProperty);
}
}
public enum Position
{
Zero = 0,
One = 1,
Two = 2
}
}
在这里,我可以看到设计时的变化:)
示例 1:
示例 2:
问题: Grid.Row、Grid.Column、Canvas.SetTop 等属性本身具有强大的 DesignTime 支持。您将它们附加到子元素,并观察 xaml 更新。它们的实现与我下面的示例有何不同?
示例:
在这个例子中,我创建了一个名为 position 的 attached 属性。我可以将 position 属性 附加到网格中的任何子元素。这样做会更新他们的行和列。
public static void SetPosition(DependencyObject obj, Positioning value) => obj.SetValue(PositionProperty, value);
public static void GetPosition(DependencyObject obj) => (Positioning)obj.GetValue(PositionProperty);
public static readonly DependencyProperty PositionProperty = DependencyProperty.RegisterAttatched( "Position", typeof(Positioning),
new PropertyMetadata( Positioning.Normal, OnPositionChanged));
public static void OnPositionChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
UIElement item = obj as UIElement;
if(item == null)
return;
switch((Positioning) e.NewValue)
{
case Positioning.Middle:
Grid.SetRow(item, 4);
Grid.SetColumn(item, 2);
break;
default:
Grid.SetRow(item, 0);
Grid.SetColumn(item, 0);
}
}
//Usage:
<Rectangle local:Position="Middle" Fill="Pink" Height="40" Width="40"/>
这在运行时间有效,但在设计时间无效。我最好的猜测是在设计时可能没有调用 OnPositionChanged?
我尝试过的事情:
- 当属性改变时调用一个函数(见上面的例子)
- 添加 FrameworkPropertyMetadataOptions.AffectsRender 等属性
- 覆盖 ItemsControl 的 OnItemsChanged() 函数
我不知道你把你的声明放在哪里了,但以下是有效的:
window:
<Window
x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfApp1"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<local:UserControl1 local:UserControl1.Position="Zero" Background="Red" />
</Grid>
</Window>
控件:
using System.Windows;
using System.Windows.Controls;
namespace WpfApp1
{
public partial class UserControl1
{
public static readonly DependencyProperty PositionProperty = DependencyProperty.RegisterAttached(
"Position", typeof(Position), typeof(UserControl1),
new PropertyMetadata(default(Position), PositionPropertyChangedCallback));
public UserControl1()
{
InitializeComponent();
}
private static void PositionPropertyChangedCallback(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
if (!(o is UIElement uiElement))
return;
var position = (Position) e.NewValue;
var value = (int) position;
Grid.SetRow(uiElement, value);
}
public static void SetPosition(DependencyObject element, Position value)
{
element.SetValue(PositionProperty, value);
}
public static Position GetPosition(DependencyObject element)
{
return (Position) element.GetValue(PositionProperty);
}
}
public enum Position
{
Zero = 0,
One = 1,
Two = 2
}
}
在这里,我可以看到设计时的变化:)
示例 1:
示例 2: