WPF:将附加属性从一个元素转移到另一个元素
本文关键字:元素 一个 转移 另一个 属性 WPF | 更新日期: 2023-09-27 18:33:55
我正在编写一个需要将现有 FrameworkElement 包装在网格控件中的 WPF 行为。
举个例子:
<Grid> <!-- Container Grid -->
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<Rectangle Height="100" Width="100" Grid.Row="1"/>
</Grid>
这是网格中的简单矩形,包含两行。使用附加属性,矩形设置为显示在网格的第 1 行中。
如果我将我的行为附加到矩形,它会将矩形包装在另一个网格中,并影响可视化树,如下所示:
<Grid> <!-- Container Grid -->
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<Grid> <!-- Wrapper Grid -->
<Rectangle Height="100" Width="100" Grid.Row="1"/>
</Grid>
</Grid>
我的问题是,在这种情况下,现在包装在新的网格控件中的矩形将显示在容器网格的第 0 行,而不是第 1 行。矩形的"网格.行"附加属性需要重新分配给包装网格控制。
我的问题是:有没有简单的方法将所有附加的属性(如Grid.Row等(从一个框架元素转移到另一个框架元素?或者任何人都可以提出解决这个问题的更好方法吗?
我的行为需要确保它附加到的元素被包装(子级(面板控件(理想情况下是网格(。行为需要灵活,并且可以连接到任何类型的元素,在任何容器,面板,装饰器等中;因此,可以拥有任何数量的需要履行的附加财产。
仅供参考,我使用以下实用程序代码来执行包装。它在此阶段是实验性的,只能处理父级为面板(网格(或装饰器(边框(的元素:
public static FrameworkElement WrapFrameworkElementWithGrid(FrameworkElement elementToWrap)
{
if (elementToWrap != null)
{
var container = new Grid();
if (elementToWrap.Parent is Panel)
{
// If the element is in a panel (grid, etc) then remove it,
// wrap it and replace it in the Children collection.
var panel = elementToWrap.Parent as Panel;
int childIndex = panel.Children.IndexOf(elementToWrap);
panel.Children.Remove(elementToWrap);
container.Children.Add(elementToWrap);
panel.Children.Insert(childIndex, container);
return container;
}
else if (elementToWrap.Parent is Decorator)
{
// If the element is in a decorator (border, etc), then remove
// it, wrap it and set the Child as the container.
var decorator = elementToWrap.Parent as Decorator;
decorator.Child = null;
container.Children.Add(elementToWrap);
decorator.Child = container;
return container;
}
else
{
// If the parent is of an unhandled type, then return the original element unwrapped.
return elementToWrap;
}
}
}
你的问题对我来说不太清楚。你到底在做什么?您是否在所有者网格中动态生成这些子项,或者您是否已经具有修复 xaml 设计?这个附加的 dp 问题是否仅与网格.行和网格列属性有关?您能否首先正确设计考试,这样您就不需要"绕来绕去"?
请您告诉我们更多关于您在做什么?
我知道这更像是一个评论,而不是对您的问题的实际答案,但以下是您找到所有附加属性的方法:
public IList<DependencyProperty> GetAttachedProperties(DependencyObject obj)
{
List<DependencyProperty> attached = new List<DependencyProperty>();
foreach (PropertyDescriptor pd in TypeDescriptor.GetProperties(obj,
new Attribute[] { new PropertyFilterAttribute(PropertyFilterOptions.All) }))
{
DependencyPropertyDescriptor dpd =
DependencyPropertyDescriptor.FromProperty(pd);
if (dpd != null && dpd.IsAttached)
{
attached.Add(dpd.DependencyProperty);
}
}
return attached;
}
因此,也许您可以在运行时加载 Xaml,然后在决定显示页面之前更改内容。
看看这个例子:
StreamReader mysr = new StreamReader("Page1.xaml");
DependencyObject rootObject = XamlReader.Load(mysr.BaseStream) as DependencyObject;
ButtoninXAML = LogicalTreeHelper.FindLogicalNode(rootObject, "button1") as Button ;
ButtoninXAML.Click += new RoutedEventHandler(Button_Click);
...
尽管如此,这一切听起来仍然很酷,我建议您首先重新考虑您的应用程序设计。