如何在 XAML 对象上设置 Attached 属性 MyPage.MyParagraph.Text
How to set Attached property MyPage.MyParagraph.Text on a XAML object
是否可以 get/set 附加属性到一个对象的几层深处?
虚拟示例:
<ContentControl local:MyPage.Paragraph1.Text="I'm actually a lot of text"/>
还有我的假人类
public static class MyPage
{
public static readonly Paragraph1 = new Paragraph();
public static Paragraph2 {get;} = new Paragraph();
}
public class Paragraph
{
public readonly DependencyProperty TextProperty;
public void SetParagraph(DependencyObject obj, string text) => obj.SetValue(TextProperty, text);
public void GetParagraph(DependencyObject obj) => (string)obj.GetValue(TextProperty);
public Paragraph()
{
//note that this is NOT a static Dependency Property. Instead, each instance of this class will be static.
TextProperty = DependencyProperty.RegisterAttached("Text", typeof(string), typeof(Paragraph), new PropertyMetadata(string.Empty));
}
}
我尝试了不同的格式,例如 Paragraph2,将 XAML 调用括在括号中,并且不寻常的“+”语法建议 here,但我不断收到如下错误:"The property 'MyPage.Paragraph1.Text' does not exist in the XML namespace '....'"、"The attachable property 'Paragraph1' was not found in type 'MyPage'," 和 "must not be a nested class."
对于附加属性,Get 和 Set 方法应该与 属性 名称相关联,而不是与定义它的 class 相关联。
如果 属性 可以附加到可视化树中任意深度的元素,我有一个适合我的辅助函数。
我会这样做 page/paragraph:
public class MyPage : Panel
{
// implementation of custom panel excluded for clarity
}
public class Paragraph
{
public static readonly DependencyProperty TextProperty = DependencyProperty.RegisterAttached(
"Text",
typeof(string),
typeof(CustomContainer),
new FrameworkPropertyMetadata(null)
);
public static void SetText(UIElement element, string value)
{
element.SetValue(TextProperty, value);
}
public static string GetText(UIElement element)
{
return (string)element.GetValue(TextProperty);
}
}
XAML:
<ctls.MyPage>
<ctls.Paragraph x:Name="anInstanceOfParagraph">
<StackPanel>
<TextBlock ctls:Paragraph.Text="ChapterTitle" Text="Chapter One: My Early Years"/>
</StackPanel>
</ctls.Paragraph>
</ctls.MyPage>
要在代码中附加一个属性:
private void AttachText(TextBlock textElement, string text)
{
Paragraph.SetText(textElement, text);
}
然后我们在 Paragraph 中找到任意嵌套的元素,这些元素附加了 属性 并使用助手设置为特定值:
var elements = WPFHelper.GetChildrenWithPropertySet(anInstanceOfParagraph,
TextProperty,
"IsIntubationCompleted");
这里是辅助函数,WPFHelper中的一个静态方法class:
/// <summary>
/// Give a property and a control, find all the child controls that
/// have a property (typically an attached property). Optionally,
/// if value !=null, it will search for an item with the property
/// set to a specific value
/// </summary>
/// <param name="parent"></param>
/// <param name="property"></param>
/// <param name="value"></param>
/// <returns></returns>
public static List<DependencyObject> GetChildrenWithPropertySet(DependencyObject parent,
DependencyProperty property, string value = null)
{
var objectsWithPropertySet = new List<DependencyObject>();
if (value == null)
{
objectsWithPropertySet.AddRange(parent.GetAllChildren()
.Where(o => o.ReadLocalValue(property) != DependencyProperty.UnsetValue));
}
else
{
objectsWithPropertySet.AddRange(parent.GetAllChildren()
.Where(o => o.ReadLocalValue(property) != DependencyProperty.UnsetValue &&
((string)o.ReadLocalValue(property)) == value));
}
return objectsWithPropertySet;
}
/// <summary>
/// returns all children in the visual true of a dependency object
/// </summary>
/// <param name="parent"></param>
/// <returns></returns>
public static IEnumerable<DependencyObject> GetAllChildren(this DependencyObject parent)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
{
// retrieve child at specified index
var directChild = (Visual)VisualTreeHelper.GetChild(parent, i);
// return found child
yield return directChild;
// return all children of the found child
foreach (var nestedChild in directChild.GetAllChildren())
yield return nestedChild;
}
}
是否可以 get/set 附加属性到一个对象的几层深处?
虚拟示例:
<ContentControl local:MyPage.Paragraph1.Text="I'm actually a lot of text"/>
还有我的假人类
public static class MyPage
{
public static readonly Paragraph1 = new Paragraph();
public static Paragraph2 {get;} = new Paragraph();
}
public class Paragraph
{
public readonly DependencyProperty TextProperty;
public void SetParagraph(DependencyObject obj, string text) => obj.SetValue(TextProperty, text);
public void GetParagraph(DependencyObject obj) => (string)obj.GetValue(TextProperty);
public Paragraph()
{
//note that this is NOT a static Dependency Property. Instead, each instance of this class will be static.
TextProperty = DependencyProperty.RegisterAttached("Text", typeof(string), typeof(Paragraph), new PropertyMetadata(string.Empty));
}
}
我尝试了不同的格式,例如 Paragraph2,将 XAML 调用括在括号中,并且不寻常的“+”语法建议 here,但我不断收到如下错误:"The property 'MyPage.Paragraph1.Text' does not exist in the XML namespace '....'"、"The attachable property 'Paragraph1' was not found in type 'MyPage'," 和 "must not be a nested class."
对于附加属性,Get 和 Set 方法应该与 属性 名称相关联,而不是与定义它的 class 相关联。
如果 属性 可以附加到可视化树中任意深度的元素,我有一个适合我的辅助函数。
我会这样做 page/paragraph:
public class MyPage : Panel
{
// implementation of custom panel excluded for clarity
}
public class Paragraph
{
public static readonly DependencyProperty TextProperty = DependencyProperty.RegisterAttached(
"Text",
typeof(string),
typeof(CustomContainer),
new FrameworkPropertyMetadata(null)
);
public static void SetText(UIElement element, string value)
{
element.SetValue(TextProperty, value);
}
public static string GetText(UIElement element)
{
return (string)element.GetValue(TextProperty);
}
}
XAML:
<ctls.MyPage>
<ctls.Paragraph x:Name="anInstanceOfParagraph">
<StackPanel>
<TextBlock ctls:Paragraph.Text="ChapterTitle" Text="Chapter One: My Early Years"/>
</StackPanel>
</ctls.Paragraph>
</ctls.MyPage>
要在代码中附加一个属性:
private void AttachText(TextBlock textElement, string text)
{
Paragraph.SetText(textElement, text);
}
然后我们在 Paragraph 中找到任意嵌套的元素,这些元素附加了 属性 并使用助手设置为特定值:
var elements = WPFHelper.GetChildrenWithPropertySet(anInstanceOfParagraph,
TextProperty,
"IsIntubationCompleted");
这里是辅助函数,WPFHelper中的一个静态方法class:
/// <summary>
/// Give a property and a control, find all the child controls that
/// have a property (typically an attached property). Optionally,
/// if value !=null, it will search for an item with the property
/// set to a specific value
/// </summary>
/// <param name="parent"></param>
/// <param name="property"></param>
/// <param name="value"></param>
/// <returns></returns>
public static List<DependencyObject> GetChildrenWithPropertySet(DependencyObject parent,
DependencyProperty property, string value = null)
{
var objectsWithPropertySet = new List<DependencyObject>();
if (value == null)
{
objectsWithPropertySet.AddRange(parent.GetAllChildren()
.Where(o => o.ReadLocalValue(property) != DependencyProperty.UnsetValue));
}
else
{
objectsWithPropertySet.AddRange(parent.GetAllChildren()
.Where(o => o.ReadLocalValue(property) != DependencyProperty.UnsetValue &&
((string)o.ReadLocalValue(property)) == value));
}
return objectsWithPropertySet;
}
/// <summary>
/// returns all children in the visual true of a dependency object
/// </summary>
/// <param name="parent"></param>
/// <returns></returns>
public static IEnumerable<DependencyObject> GetAllChildren(this DependencyObject parent)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
{
// retrieve child at specified index
var directChild = (Visual)VisualTreeHelper.GetChild(parent, i);
// return found child
yield return directChild;
// return all children of the found child
foreach (var nestedChild in directChild.GetAllChildren())
yield return nestedChild;
}
}