gpt4 book ai didi

wpf - 如何使用子定义的附加属性?

转载 作者:行者123 更新时间:2023-12-04 19:07:27 31 4
gpt4 key购买 nike

1. 问题

众所周知,Attached Property广泛扩展了wpf中的property系统。但是我们熟悉的例子几乎都是父定义 的,例如 DockPanel.Dock/Grid.Row 等等。 但是在查看MSDN中的文档后,我发现Attached Property还有一些其他用法:

From MSDN:Attached Properties Overview / How Attached Properties Are Used by the Owning Type

1.The type that defines the attached property is designed so that it can be the parent element of the elements that will set values for the attached property. The type then iterates its child objects through internal logic against some object tree structure, obtains the values, and acts on those values in some manner.(Parent-Defined)

2.The type that defines the attached property will be used as the child element for a variety of possible parent elements and content models.(Child-Defined)

3.The type that defines the attached property represents a service. Other types set values for the attached property. Then, when the element that set the property is evaluated in the context of the service, the attached property values are obtained through internal logic of the service class.(Use as a Common Service)



2.试用

由于附加属性可以由用户定义,我想也许我们可以使用“CallBackMethod”来处理它。所以我编写了一些试验来验证我的想法(第 4 部分代码):

1.Customize a child control ("Son") which defined a attached property named "CellBorderThicknessProperty" and use "PropertyChangedCallBack" to update the layout;

2.Create a parent control ("Father") which's template contains the child control.

3.Use the parent control in a Window and set the child.CellBorderThickness's value;



3. 问题

1.As you see,It's not a good way to expose the "Parent Type" in "Child Type",especially we won't how many Parents there would be...

2.This Trial didnt work well,'Cus when the "PropertyChangedCallBack" was fired,the Father's template was not applied yet!So,Father.SetBorderThickness() will do nothing!



有没有使用过 Child-Defined 附加属性的例子?它是如何工作的?

我非常想知道 MS 开发人员如何处理 Child-Defined 的。

例如: 怎么样? WPFToolkit 中的 ScrollViwer.VerticalScrollBarVisibility:DataGrid ?

4. 代码

儿子控制( child )
<Style TargetType={x:Type Son}>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border BorderThickness={TemplateBinding CellBorderThickness}>
...
</Border>
</ControlTemplate>
<Setter.Value>
</Setter>


 public class Son: Control
{
public static readonly DependencyProperty CellBorderThicknessProperty = DependencyProperty.RegisterAttached("CellBorderThickness", typeof(Thickness), typeof(Son), new FrameworkPropertyMetadata(new Thickness(0.2), FrameworkPropertyMetadataOptions.AffectsRender, CellBorderThicknessProperty_ChangedCallBack));

public static void SetCellBorderThickness(UIElement obj, Thickness value)
{
obj.SetValue(Son.CellBorderThicknessProperty, value);
}

public static Thickness GetCellBorderThickness(UIElement obj)
{
return (Thickness)obj.GetValue(Son.CellBorderThicknessProperty);
}

public Thickness CellBorderThickness
{
//With this, CellBorderThickness can be used as a normal dependency property.
get { return (Thickness)GetValue(CellBorderThicknessProperty); }
set { SetValue(CellBorderThicknessProperty, value); }
}

static void CellBorderThicknessProperty_ChangedCallBack(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if ((d as Father) != null)
{
// Try to update the Son's CellBorderThickness which is the child element of the Father.
d.SetBorderThickness(e.NewValue);
}
}
}

父控制(父)
 <Style TargetType={x:Type Father}>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border>
<Son></Son>
</Border>
</ControlTemplate>
<Setter.Value>
</Setter>


 public class Father:Control
{
private Son childControl;

public void override OnApplyTemplate()
{
childControl=(Son)GetTemplateChild("PART_ChildControl");//Here is a problem!!
}

public void SetBorderThickness(Thickness value)
{
if(childControl==null)
childControl.CellBorderThickness=value;
}
}

window
 <Window>
<Grid>
<Father Son.CellBorderThichness="5"></Father>
</Grid>
<Window>

最佳答案

我以你的例子为基础,去掉了太多,得到了这个例子。我删除了它们以显示一个最小的工作示例。

首先,我删除了 CellBorderThickness属性,因为已经附加了依赖属性。

Son

// Removed
public Thickness CellBorderThickness
{
get { return (Thickness)GetValue(CellBorderThicknessProperty); }
set { SetValue(CellBorderThicknessProperty, value); }
}

在我父亲的控制中,我删除了 OnApplyTemplate() , 并在函数中 SetBorderThickness()利用附加依赖属性的机会来设置值:

Father
// Removed
OnApplyTemplate() { ... }

// Add
Son.SetCellBorderThickness(childControl, value);

下面是一个完整的例子。示例结构:

enter image description here

XAML
Styles
儿子
<Style TargetType="{x:Type SonNamespace:Son}">
<Setter Property="Background" Value="Gainsboro" />
<Setter Property="BorderBrush" Value="Black" />
<Setter Property="Width" Value="100" />
<Setter Property="Height" Value="100" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="VerticalContentAlignment" Value="Center" />

<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding SonNamespace:Son.CellBorderThickness}">

<ContentPresenter Content="I'am a Son"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

父亲
<Style TargetType="{x:Type FatherNamespace:Father}">
<Setter Property="Background" Value="AliceBlue" />
<Setter Property="BorderBrush" Value="Black" />
<Setter Property="Width" Value="100" />
<Setter Property="Height" Value="100" />
<Setter Property="HorizontalAlignment" Value="Right" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="VerticalContentAlignment" Value="Center" />

<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding SonNamespace:Son.CellBorderThickness}">

<ContentPresenter Content="I'am a Father"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

主窗口
<Grid>
<SonNamespace:Son />

<FatherNamespace:Father SonNamespace:Son.CellBorderThickness="6" />
</Grid>

Code

儿子
public class Son : Control
{
public static readonly DependencyProperty CellBorderThicknessProperty =
DependencyProperty.RegisterAttached("CellBorderThickness",
typeof(Thickness), typeof(Son),
new FrameworkPropertyMetadata(new Thickness(2),
FrameworkPropertyMetadataOptions.AffectsRender,
CellBorderThicknessProperty_ChangedCallBack));

public static void SetCellBorderThickness(UIElement obj, Thickness value)
{
obj.SetValue(Son.CellBorderThicknessProperty, value);
}

public static Thickness GetCellBorderThickness(UIElement obj)
{
return (Thickness)obj.GetValue(Son.CellBorderThicknessProperty);
}

private static void CellBorderThicknessProperty_ChangedCallBack(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Father father = d as Father;

if (father != null)
{
father.SetBorderThickness((Thickness)e.NewValue);
}
}
}

父亲
public class Father : Control
{
private Son childControl;

public void SetBorderThickness(Thickness value)
{
if (childControl != null)
{
Son.SetCellBorderThickness(childControl, value);
}
}
}

Output

enter image description here

项目可在此 link .

关于wpf - 如何使用子定义的附加属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20987450/

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