gpt4 book ai didi

c# - WPF 附加属性在设计时无效(xaml 编辑器)

转载 作者:太空宇宙 更新时间:2023-11-03 22:54:02 25 4
gpt4 key购买 nike

我有一个在运行时运行良好的附加属性,我希望它在设计时也能运行。我已经阅读了一些文档并遵循了一些教程,但我认为他们比我更熟悉。

此 DP(来自 source blog post (microsoft.co.il))的目的是:

  • 附加到任何面板类型
  • 设置每个项目子项目的边距
  • ( future )最后一个 child 的自定义边距

如何使该属性在设计器中具有与在运行时相同的效果?它会影响布局,所以我认为了解那里发生的事情也很重要。

简化的 XAML:

<StackPanel Orientation="Horizontal" local:PanelItems.Margin="0,0,10,0">
<TextBox Width="120" Text="{Binding Email}"/>
<Button Content="Search" Command="{Binding SearchCommand}"/>
</StackPanel>

当前类(在运行时工作正常)。

我已经删除了从 DependencyObject 继承,因为这对这种情况没有帮助(我正在关注 msdn 示例)。我想这些示例不处理附加属性。

public static class PanelItems : DependencyObject
{
public static readonly DependencyProperty MarginProperty =
DependencyProperty.RegisterAttached(
"Margin", typeof(Thickness), typeof(PanelItems),
new UIPropertyMetadata(new Thickness(), MarginChangedCallback)
);

public static Thickness GetMargin(DependencyObject obj)
{
return (Thickness)obj.GetValue(MarginProperty);
}

public static void SetMargin(DependencyObject obj, Thickness value)
{
obj.SetValue(MarginProperty, value);
}

public static void MarginChangedCallback(object sender, DependencyPropertyChangedEventArgs e)
{
// requires a panel control (e.g. a StackPanel)
var panel = sender as Panel;
if (panel == null) return;
panel.Loaded += new RoutedEventHandler(OnPanelLoaded);
}

static void OnPanelLoaded(object sender, RoutedEventArgs e)
{
var panel = sender as Panel;
foreach (var child in panel.Children.OfType<FrameworkElement>())
child.Margin = PanelItems.GetMargin(panel);
}
}

解决方案说明

我添加了一个扩展方法来检查是否为给定对象设置了值,它允许仅针对直接子对象。我看不到其他方法,因为没有上下文返回到导致级联的原始更改。

public static class DependencyExtensions
{
/// <summary>
/// Checks if a DependencObject has a value set for the Dependency Property.
/// Element is an object for conveninence purpose, and the return value is
/// always false if it is not a DependencyObject (e.g. a UI element)
/// </summary>
/// <param name="property">The DependencyProperty to check</param>
/// <param name="element">The element (a DependencyObject) to check against</param>
/// <returns></returns>
public static bool IsSetFor(this DependencyProperty property, object element)
{
if (element is DependencyObject d)
{
return d.ReadLocalValue(property) != DependencyProperty.UnsetValue;
}
return false;
}
}

之后我稍微修改了事件以检查两者。嵌套面板也能正常工作;内部面板按照外部面板规则,内部子项获得正确的边距。

if (sender is FrameworkElement el && MarginProperty.IsSetFor(el.Parent))
{
el.Margin = (Thickness)args.NewValue;
}

注意:它也可以调用 GetMargin(el as DependencyObject),尽管值与子级的 NewValue 相同。

最后一点:我在设计器上关闭了project code,所以无论我做什么我都看不到那里的变化。这是具有巨大效果的无标签小按钮:Enable Project Code (e.g. user code in the designer)

最佳答案

这是具有值继承的 Margin 属性的快速草稿,因此它会自动应用于所有子元素。

除了所有子元素之外,Margin 也应用于 Panel 本身,您可能会以某种方式尝试避免这种情况(也许通过简单地检查目标元素是否为 Panel)。

public static class PanelItems
{
public static readonly DependencyProperty MarginProperty =
DependencyProperty.RegisterAttached(
"Margin", typeof(Thickness), typeof(PanelItems),
new FrameworkPropertyMetadata(new Thickness(),
FrameworkPropertyMetadataOptions.Inherits, MarginChangedCallback));

public static Thickness GetMargin(DependencyObject obj)
{
return (Thickness)obj.GetValue(MarginProperty);
}

public static void SetMargin(DependencyObject obj, Thickness value)
{
obj.SetValue(MarginProperty, value);
}

private static void MarginChangedCallback(
object sender, DependencyPropertyChangedEventArgs e)
{
var element = sender as FrameworkElement;

if (element != null && !(element is Panel))
{
element.Margin = (Thickness)e.NewValue;
}
}
}

关于c# - WPF 附加属性在设计时无效(xaml 编辑器),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46313372/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com