我正在编写一个需要在Grid控件中包装现有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行中。
如果我将我的行为附加到Rectangle,它会将Rectangle包装在另一个Grid中,并像这样影响可视树:
<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>
我的问题是,在这种情况下,现在包装在新Grid控件中的Rectangle将出现在第0行,而不是容器网格的第1行。 Rectangle的'Grid.Row'附加属性需要重新分配给Wrapper Grid控件。
我的问题是:有没有简单的方法将所有附加属性(例如Grid.Row等)从一个FrameworkElement传输到另一个?或者,任何人都可以建议更好的方法来解决这个问题吗?
我的行为需要确保它所附着的元素被包裹(一个孩子)一个面板控件(理想情况下是一个Grid)。行为需要灵活,并且可以附加到任何类型的元素,任何容器,面板,装饰器等;因此可能有任何需要尊重的附加属性。
仅供参考,我正在使用以下实用程序代码执行包装。它在这个阶段是实验性的,并且只能处理父类型为Panel(Grid)或Decorator(Border)的元素:
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;
}
}
}
答案 0 :(得分:0)
我的问题不是很清楚。你到底在做什么?您是否在所有者Grid中动态构建这些子项,或者您是否已经修复了xaml设计?这个附加的dp问题只涉及Grid.Row和Grid.Column属性吗?你能否在一开始就正确地设计你的考试,这样你就不需要&#34;包装&#34;围绕?
请告诉我们更多关于你的最新动态?
我知道这不仅仅是对您的问题的实际答案的评论,而是以下是您如何找到所有附加属性:
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);
...
所有声音仍然很酷,我建议你先重新考虑你的应用程序设计。