如何解决 ItemsPanelTemplate 中 Grid.Row / Column 的错误?
How to defeat a bug with Grid.Row / Column in ItemsPanelTemplate?
创建了一个简单的附件 属性 以简化元素模板的绑定。
而不是这个:
<ItemsControl ItemsSource="{Binding Mode=OneWay, Source={StaticResource Points.Grid}}"
ItemsPanel="{StaticResource Grid.Panel}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="Point">
<Ellipse Fill="Coral"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Grid.Row" Value="{Binding Y}"/>
<Setter Property="Grid.Column" Value="{Binding X}"/>
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
你可以这样走:
<ItemsControl Grid.Row="1"
ItemsSource="{Binding Mode=OneWay, Source={StaticResource Points.Grid}}"
ItemsPanel="{StaticResource Grid.Panel}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="Point">
<Ellipse Fill="LightBlue"
pa:Grid.Row="{Binding Y}"
pa:Grid.Column="{Binding X}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
附上完整代码属性:
public static partial class Grid
{
public static int GetRow(FrameworkElement element)
{
return (int)element.GetValue(RowProperty);
}
public static void SetRow(FrameworkElement element, int value)
{
element.SetValue(RowProperty, value);
}
// Using a DependencyProperty as the backing store for Row. This enables animation, styling, binding, etc...
public static readonly DependencyProperty RowProperty =
DependencyProperty.RegisterAttached("Row", typeof(int), typeof(Grid),
new FrameworkPropertyMetadata
(
0,
FrameworkPropertyMetadataOptions.AffectsParentArrange | FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
RowChanged
));
private static void RowChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (!(d is FrameworkElement element))
throw new ArgumentException("Must be FrameworkElement", nameof(d));
FrameworkElement parent;
while ((parent = VisualTreeHelper.GetParent(element) as FrameworkElement) != null && !(parent is System.Windows.Controls.Grid))
element = parent;
if (parent is System.Windows.Controls.Grid grid)
element.SetValue(System.Windows.Controls.Grid.RowProperty, (int)e.NewValue);
}
private static void GridLoaded(object sender, RoutedEventArgs e)
=> ((System.Windows.Controls.Grid)sender).InvalidateMeasure();
public static int GetColumn(FrameworkElement element)
{
return (int)element.GetValue(ColumnProperty);
}
public static void SetColumn(FrameworkElement element, int value)
{
element.SetValue(ColumnProperty, value);
}
// Using a DependencyProperty as the backing store for Column. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ColumnProperty =
DependencyProperty.RegisterAttached("Column", typeof(int), typeof(Grid),
new FrameworkPropertyMetadata
(
0,
FrameworkPropertyMetadataOptions.AffectsParentArrange | FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
ColumnChanged
));
private static void ColumnChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (!(d is FrameworkElement element))
throw new ArgumentException("Must be FrameworkElement", nameof(d));
FrameworkElement parent;
while ((parent = VisualTreeHelper.GetParent(element) as FrameworkElement) != null && !(parent is System.Windows.Controls.Grid))
element = parent;
if (parent is System.Windows.Controls.Grid grid)
element.SetValue(System.Windows.Controls.Grid.ColumnProperty, (int)e.NewValue);
}
}
属性 并不复杂。
使用 Canvas,同样可以正常工作。
对于 Grid,在使用元素附加集合或将第一个元素添加到集合时会出现问题 - 元素显示在 Grid 中而不考虑它们的位置。
虽然在可视化树和属性浏览器中查看时, Grid.Row / Column 的附加属性设置正确。
window 的最细微变化,元素就位。
在我看来,这是一个坦率的错误。
但是怎么处理呢?
完整 XAML 演示代码:
<Window x:Class="AttachedPropertiesWPF.BindParentWind"
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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:AttachedPropertiesWPF"
mc:Ignorable="d"
Title="BindParentWind" Height="450" Width="800"
xmlns:pa="clr-namespace:AttachedProperties;assembly=AttachedProperties">
<Window.Resources>
<x:Array x:Key="Points.Grid" Type="Point">
<Point X="1" Y="0"/>
<Point X="0" Y="2"/>
<Point X="2" Y="1"/>
</x:Array>
<ItemsPanelTemplate x:Key="Grid.Panel">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
</Grid>
</ItemsPanelTemplate>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<ItemsControl ItemsSource="{Binding Mode=OneWay, Source={StaticResource Points.Grid}}"
ItemsPanel="{StaticResource Grid.Panel}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="Point">
<Ellipse Fill="Coral"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Grid.Row" Value="{Binding Y}"/>
<Setter Property="Grid.Column" Value="{Binding X}"/>
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
<ItemsControl Grid.Row="1"
ItemsSource="{Binding Mode=OneWay, Source={StaticResource Points.Grid}}"
ItemsPanel="{StaticResource Grid.Panel}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="Point">
<Ellipse Fill="LightBlue"
pa:Grid.Row="{Binding Y}"
pa:Grid.Column="{Binding X}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</Window>
这样的输出:
它应该是这样的:
欢迎来到 SO!
老实说,这段代码有很多很多问题,但我会坚持你发布的内容....
Clemens 是正确的,看起来您对应该如何在网格上定位元素有点困惑。在您的第一个 ItemsControl 中,您通过 ItemContainerStyle 来完成它,在第二个 ItemsControl 中,您将它直接应用于 Ellipse(尽管令人困惑的是,使用您的自定义 Grid 助手 DP)。您对第一个控件所做的操作不会影响第二个控件,因此您看到的布局行为当然也会在它们之间有所不同。
项目模板(例如您的椭圆)不会直接添加到父面板容器中,它们会封装在 ContentPresenter 中。所以你的第一个控制是正确的。在第二个 ItemsControl 中也设置 ItemContainerStyle,从第二个控件中的 Ellipse 标记中删除 ap:Grid.Row 和 ap:Grid.Column 设置器,并完全摆脱那个 Grid 助手 class , 你不需要它。
最初在 ContentPresenter 上设置 Grid.Row
和 Grid.Column
不会导致另一个布局循环,这似乎是一个计时问题。
虽然删除整个助手 class 并直接在 ItemContainerStyle 中设置 Grid 属性显然是个好主意,但一个丑陋的解决方法是异步设置 Grid 属性,如下所示:
public class ContentPresenterHelper
{
public static readonly DependencyProperty ColumnProperty =
DependencyProperty.RegisterAttached(
"Column", typeof(int), typeof(ContentPresenterHelper),
new PropertyMetadata(0, ColumnPropertyChanged));
public static readonly DependencyProperty RowProperty =
DependencyProperty.RegisterAttached(
"Row", typeof(int), typeof(ContentPresenterHelper),
new PropertyMetadata(0, RowPropertyChanged));
public static int GetRow(DependencyObject o)
{
return (int)o.GetValue(RowProperty);
}
public static void SetColumn(DependencyObject o, int value)
{
o.SetValue(ColumnProperty, value);
}
public static int GetColumn(DependencyObject o)
{
return (int)o.GetValue(ColumnProperty);
}
public static void SetRow(DependencyObject o, int value)
{
o.SetValue(RowProperty, value);
}
private static void ColumnPropertyChanged(
DependencyObject o, DependencyPropertyChangedEventArgs e)
{
o.Dispatcher.InvokeAsync(() =>
FindContentPresenterParent(o)?.SetValue(
Grid.ColumnProperty, (int)e.NewValue));
}
private static void RowPropertyChanged(
DependencyObject o, DependencyPropertyChangedEventArgs e)
{
o.Dispatcher.InvokeAsync(() =>
FindContentPresenterParent(o)?.SetValue(
Grid.RowProperty, (int)e.NewValue));
}
private static ContentPresenter FindContentPresenterParent(DependencyObject element)
{
if (element == null)
{
return null;
}
var parent = VisualTreeHelper.GetParent(element);
return (parent as ContentPresenter) ?? FindContentPresenterParent(parent);
}
}
附加属性的工作实现:
public static partial class Grid
{
public static int GetRow(FrameworkElement element)
{
return (int)element.GetValue(RowProperty);
}
public static void SetRow(FrameworkElement element, int value)
{
element.SetValue(RowProperty, value);
}
// Using a DependencyProperty as the backing store for Row. This enables animation, styling, binding, etc...
public static readonly DependencyProperty RowProperty =
DependencyProperty.RegisterAttached("Row", typeof(int), typeof(Grid),
new FrameworkPropertyMetadata
(
0,
FrameworkPropertyMetadataOptions.AffectsParentArrange | FrameworkPropertyMetadataOptions.AffectsParentMeasure
| FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure
| FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
RowChanged
));
private static void RowChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (!(d is FrameworkElement element))
throw new ArgumentException("Must be FrameworkElement", nameof(d));
FrameworkElement parent;
while ((parent = VisualTreeHelper.GetParent(element) as FrameworkElement) != null && !(parent is System.Windows.Controls.Grid))
element = parent;
if (parent is System.Windows.Controls.Grid grid)
element.Dispatcher.BeginInvoke((Action<FrameworkElement, DependencyProperty, object>)SetValueAsync, element, System.Windows.Controls.Grid.RowProperty, (int)e.NewValue);
}
private static void SetValueAsync(FrameworkElement element, DependencyProperty property, object value)
=> element.SetValue(property, value);
public static int GetColumn(FrameworkElement element)
{
return (int)element.GetValue(ColumnProperty);
}
public static void SetColumn(FrameworkElement element, int value)
{
element.SetValue(ColumnProperty, value);
}
// Using a DependencyProperty as the backing store for Column. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ColumnProperty =
DependencyProperty.RegisterAttached("Column", typeof(int), typeof(Grid),
new FrameworkPropertyMetadata
(
0,
FrameworkPropertyMetadataOptions.AffectsParentArrange | FrameworkPropertyMetadataOptions.AffectsParentMeasure
| FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure
| FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
ColumnChanged
));
private static void ColumnChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (!(d is FrameworkElement element))
throw new ArgumentException("Must be FrameworkElement", nameof(d));
FrameworkElement parent;
while ((parent = VisualTreeHelper.GetParent(element) as FrameworkElement) != null && !(parent is System.Windows.Controls.Grid))
element = parent;
if (parent is System.Windows.Controls.Grid grid)
element.Dispatcher.BeginInvoke((Action<FrameworkElement, DependencyProperty, object>)SetValueAsync, element, System.Windows.Controls.Grid.ColumnProperty, (int)e.NewValue);
}
}
我还没有弄清楚基本属性 Grid 的不可理解行为的原因。Row/Column。
稍后我会看他们的源代码。
如果我明白原因,我会post在这里。
创建了一个简单的附件 属性 以简化元素模板的绑定。 而不是这个:
<ItemsControl ItemsSource="{Binding Mode=OneWay, Source={StaticResource Points.Grid}}"
ItemsPanel="{StaticResource Grid.Panel}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="Point">
<Ellipse Fill="Coral"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Grid.Row" Value="{Binding Y}"/>
<Setter Property="Grid.Column" Value="{Binding X}"/>
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
你可以这样走:
<ItemsControl Grid.Row="1"
ItemsSource="{Binding Mode=OneWay, Source={StaticResource Points.Grid}}"
ItemsPanel="{StaticResource Grid.Panel}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="Point">
<Ellipse Fill="LightBlue"
pa:Grid.Row="{Binding Y}"
pa:Grid.Column="{Binding X}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
附上完整代码属性:
public static partial class Grid
{
public static int GetRow(FrameworkElement element)
{
return (int)element.GetValue(RowProperty);
}
public static void SetRow(FrameworkElement element, int value)
{
element.SetValue(RowProperty, value);
}
// Using a DependencyProperty as the backing store for Row. This enables animation, styling, binding, etc...
public static readonly DependencyProperty RowProperty =
DependencyProperty.RegisterAttached("Row", typeof(int), typeof(Grid),
new FrameworkPropertyMetadata
(
0,
FrameworkPropertyMetadataOptions.AffectsParentArrange | FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
RowChanged
));
private static void RowChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (!(d is FrameworkElement element))
throw new ArgumentException("Must be FrameworkElement", nameof(d));
FrameworkElement parent;
while ((parent = VisualTreeHelper.GetParent(element) as FrameworkElement) != null && !(parent is System.Windows.Controls.Grid))
element = parent;
if (parent is System.Windows.Controls.Grid grid)
element.SetValue(System.Windows.Controls.Grid.RowProperty, (int)e.NewValue);
}
private static void GridLoaded(object sender, RoutedEventArgs e)
=> ((System.Windows.Controls.Grid)sender).InvalidateMeasure();
public static int GetColumn(FrameworkElement element)
{
return (int)element.GetValue(ColumnProperty);
}
public static void SetColumn(FrameworkElement element, int value)
{
element.SetValue(ColumnProperty, value);
}
// Using a DependencyProperty as the backing store for Column. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ColumnProperty =
DependencyProperty.RegisterAttached("Column", typeof(int), typeof(Grid),
new FrameworkPropertyMetadata
(
0,
FrameworkPropertyMetadataOptions.AffectsParentArrange | FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
ColumnChanged
));
private static void ColumnChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (!(d is FrameworkElement element))
throw new ArgumentException("Must be FrameworkElement", nameof(d));
FrameworkElement parent;
while ((parent = VisualTreeHelper.GetParent(element) as FrameworkElement) != null && !(parent is System.Windows.Controls.Grid))
element = parent;
if (parent is System.Windows.Controls.Grid grid)
element.SetValue(System.Windows.Controls.Grid.ColumnProperty, (int)e.NewValue);
}
}
属性 并不复杂。 使用 Canvas,同样可以正常工作。 对于 Grid,在使用元素附加集合或将第一个元素添加到集合时会出现问题 - 元素显示在 Grid 中而不考虑它们的位置。 虽然在可视化树和属性浏览器中查看时, Grid.Row / Column 的附加属性设置正确。 window 的最细微变化,元素就位。
在我看来,这是一个坦率的错误。 但是怎么处理呢?
完整 XAML 演示代码:
<Window x:Class="AttachedPropertiesWPF.BindParentWind"
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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:AttachedPropertiesWPF"
mc:Ignorable="d"
Title="BindParentWind" Height="450" Width="800"
xmlns:pa="clr-namespace:AttachedProperties;assembly=AttachedProperties">
<Window.Resources>
<x:Array x:Key="Points.Grid" Type="Point">
<Point X="1" Y="0"/>
<Point X="0" Y="2"/>
<Point X="2" Y="1"/>
</x:Array>
<ItemsPanelTemplate x:Key="Grid.Panel">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
</Grid>
</ItemsPanelTemplate>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<ItemsControl ItemsSource="{Binding Mode=OneWay, Source={StaticResource Points.Grid}}"
ItemsPanel="{StaticResource Grid.Panel}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="Point">
<Ellipse Fill="Coral"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Grid.Row" Value="{Binding Y}"/>
<Setter Property="Grid.Column" Value="{Binding X}"/>
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
<ItemsControl Grid.Row="1"
ItemsSource="{Binding Mode=OneWay, Source={StaticResource Points.Grid}}"
ItemsPanel="{StaticResource Grid.Panel}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="Point">
<Ellipse Fill="LightBlue"
pa:Grid.Row="{Binding Y}"
pa:Grid.Column="{Binding X}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</Window>
这样的输出:
它应该是这样的:
欢迎来到 SO!
老实说,这段代码有很多很多问题,但我会坚持你发布的内容....
Clemens 是正确的,看起来您对应该如何在网格上定位元素有点困惑。在您的第一个 ItemsControl 中,您通过 ItemContainerStyle 来完成它,在第二个 ItemsControl 中,您将它直接应用于 Ellipse(尽管令人困惑的是,使用您的自定义 Grid 助手 DP)。您对第一个控件所做的操作不会影响第二个控件,因此您看到的布局行为当然也会在它们之间有所不同。
项目模板(例如您的椭圆)不会直接添加到父面板容器中,它们会封装在 ContentPresenter 中。所以你的第一个控制是正确的。在第二个 ItemsControl 中也设置 ItemContainerStyle,从第二个控件中的 Ellipse 标记中删除 ap:Grid.Row 和 ap:Grid.Column 设置器,并完全摆脱那个 Grid 助手 class , 你不需要它。
最初在 ContentPresenter 上设置 Grid.Row
和 Grid.Column
不会导致另一个布局循环,这似乎是一个计时问题。
虽然删除整个助手 class 并直接在 ItemContainerStyle 中设置 Grid 属性显然是个好主意,但一个丑陋的解决方法是异步设置 Grid 属性,如下所示:
public class ContentPresenterHelper
{
public static readonly DependencyProperty ColumnProperty =
DependencyProperty.RegisterAttached(
"Column", typeof(int), typeof(ContentPresenterHelper),
new PropertyMetadata(0, ColumnPropertyChanged));
public static readonly DependencyProperty RowProperty =
DependencyProperty.RegisterAttached(
"Row", typeof(int), typeof(ContentPresenterHelper),
new PropertyMetadata(0, RowPropertyChanged));
public static int GetRow(DependencyObject o)
{
return (int)o.GetValue(RowProperty);
}
public static void SetColumn(DependencyObject o, int value)
{
o.SetValue(ColumnProperty, value);
}
public static int GetColumn(DependencyObject o)
{
return (int)o.GetValue(ColumnProperty);
}
public static void SetRow(DependencyObject o, int value)
{
o.SetValue(RowProperty, value);
}
private static void ColumnPropertyChanged(
DependencyObject o, DependencyPropertyChangedEventArgs e)
{
o.Dispatcher.InvokeAsync(() =>
FindContentPresenterParent(o)?.SetValue(
Grid.ColumnProperty, (int)e.NewValue));
}
private static void RowPropertyChanged(
DependencyObject o, DependencyPropertyChangedEventArgs e)
{
o.Dispatcher.InvokeAsync(() =>
FindContentPresenterParent(o)?.SetValue(
Grid.RowProperty, (int)e.NewValue));
}
private static ContentPresenter FindContentPresenterParent(DependencyObject element)
{
if (element == null)
{
return null;
}
var parent = VisualTreeHelper.GetParent(element);
return (parent as ContentPresenter) ?? FindContentPresenterParent(parent);
}
}
附加属性的工作实现:
public static partial class Grid
{
public static int GetRow(FrameworkElement element)
{
return (int)element.GetValue(RowProperty);
}
public static void SetRow(FrameworkElement element, int value)
{
element.SetValue(RowProperty, value);
}
// Using a DependencyProperty as the backing store for Row. This enables animation, styling, binding, etc...
public static readonly DependencyProperty RowProperty =
DependencyProperty.RegisterAttached("Row", typeof(int), typeof(Grid),
new FrameworkPropertyMetadata
(
0,
FrameworkPropertyMetadataOptions.AffectsParentArrange | FrameworkPropertyMetadataOptions.AffectsParentMeasure
| FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure
| FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
RowChanged
));
private static void RowChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (!(d is FrameworkElement element))
throw new ArgumentException("Must be FrameworkElement", nameof(d));
FrameworkElement parent;
while ((parent = VisualTreeHelper.GetParent(element) as FrameworkElement) != null && !(parent is System.Windows.Controls.Grid))
element = parent;
if (parent is System.Windows.Controls.Grid grid)
element.Dispatcher.BeginInvoke((Action<FrameworkElement, DependencyProperty, object>)SetValueAsync, element, System.Windows.Controls.Grid.RowProperty, (int)e.NewValue);
}
private static void SetValueAsync(FrameworkElement element, DependencyProperty property, object value)
=> element.SetValue(property, value);
public static int GetColumn(FrameworkElement element)
{
return (int)element.GetValue(ColumnProperty);
}
public static void SetColumn(FrameworkElement element, int value)
{
element.SetValue(ColumnProperty, value);
}
// Using a DependencyProperty as the backing store for Column. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ColumnProperty =
DependencyProperty.RegisterAttached("Column", typeof(int), typeof(Grid),
new FrameworkPropertyMetadata
(
0,
FrameworkPropertyMetadataOptions.AffectsParentArrange | FrameworkPropertyMetadataOptions.AffectsParentMeasure
| FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure
| FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
ColumnChanged
));
private static void ColumnChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (!(d is FrameworkElement element))
throw new ArgumentException("Must be FrameworkElement", nameof(d));
FrameworkElement parent;
while ((parent = VisualTreeHelper.GetParent(element) as FrameworkElement) != null && !(parent is System.Windows.Controls.Grid))
element = parent;
if (parent is System.Windows.Controls.Grid grid)
element.Dispatcher.BeginInvoke((Action<FrameworkElement, DependencyProperty, object>)SetValueAsync, element, System.Windows.Controls.Grid.ColumnProperty, (int)e.NewValue);
}
}
我还没有弄清楚基本属性 Grid 的不可理解行为的原因。Row/Column。 稍后我会看他们的源代码。 如果我明白原因,我会post在这里。