我正在尝试利用从窗口到UserControl的属性值继承。据我所知,您可以通过声明附加的DependencyProperty(与FrameworkPropertyMetadataOptions.Inherits选项一起)来实现此目的。
MainWindow.xaml:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" xmlns:my="clr-namespace:WpfApplication1" Name="BobWindow">
<Grid>
<Label Content="MainWindow" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="85,2,0,0" Name="textBox1" VerticalAlignment="Top" Width="120" Text="{Binding Path=Test, ElementName=BobWindow}" />
<my:UserControl1 HorizontalAlignment="Left" Margin="157,108,0,0" x:Name="userControl11" VerticalAlignment="Top" />
</Grid>
</Window>
MainWindow.xaml.cs:
using System;
using System.Windows;
namespace WpfApplication1
{
public partial class MainWindow : Window
{
public static readonly DependencyProperty TestProperty = DependencyProperty.RegisterAttached
(
"Test",
typeof(String),
typeof(MainWindow),
new FrameworkPropertyMetadata
(
null,
FrameworkPropertyMetadataOptions.Inherits
)
);
public String Test
{
get { return (String)GetValue(TestProperty); }
set { SetValue(TestProperty, value); }
}
public MainWindow()
{
InitializeComponent();
Test = "Yip!";
}
}
}
UserControl1.xaml:
<UserControl x:Class="WpfApplication1.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300" Name="BobControl">
<Grid>
<Label Content="UserControl1" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="85,2,0,0" Name="textBox1" VerticalAlignment="Top" Width="120" Text="{Binding Path=Test, ElementName=BobControl}" />
</Grid>
</UserControl>
UserControl1.xaml.cs:
using System;
using System.Windows;
using System.Windows.Controls;
namespace WpfApplication1
{
public partial class UserControl1 : UserControl
{
public static readonly DependencyProperty TestProperty = DependencyProperty.RegisterAttached
(
"Test",
typeof(String),
typeof(UserControl1),
new FrameworkPropertyMetadata
(
null,
FrameworkPropertyMetadataOptions.Inherits
)
);
public String Test
{
get { return (String)GetValue(TestProperty); }
set { SetValue(TestProperty, value); }
}
public UserControl1()
{
InitializeComponent();
}
}
}
我无法找到实现此目的的明确示例。在MainWindow和UserControl1中使用RegisterAttached是我最好的猜测。肯定有一些我想念的东西!
更新
我希望能够在任意结构中创建我的控件,将值设置在树的顶部并使默认值向下流动(类似于DataContext的工作方式)。当TestProperty不在MainWindow和UserControl1的共同祖先类中时,这是否可行?
另外,我想避免引用源类,因为有时它会是一个Window,但在其他情况下它可能是Windows窗体中的主机控件。这可能吗?
RESOLVE
我认为我的困惑源于想要使用非附加依赖属性的语法来实现值继承。我想使用以下xaml:
<Window ... Test="Fred" />
使用以下语法访问UserControl中的继承值:
string Value = this.Test;
但是,根据Microsoft的Property Value Inheritance页面,如果您希望继承属性值,则必须通过附加属性。
如果上面的代码被正确重写(使用静态getter / setter方法声明属性一次),那么我的xaml将如下所示:
<Window ... my:MainWindow.Test="Fred" />
我在UserControl中的代码看起来像这样:
string Value = MainWindow.GetTest( this );
答案 0 :(得分:1)
你在这里犯的错误是两次申报财产。只需在MainWindow中声明它,而不是在UserControl1中声明它。然后在MainWindow中声明静态getter和setter方法:
public static string GetTest(DependencyObject obj)
{
return (String)obj.GetValue(TestProperty);
}
public static void SetTest(DependencyObject obj, string value)
{
obj.SetValue(TestProperty, value);
}
在此处获取有关custom attached properties。
的更多信息现在,当UserControl1位于MainWindow的元素树中的某个位置时,尝试在初始化后使用UserControl1执行以下操作:
UserControl1 uc = this; // for example in a UserControl1 event handler
string test = MainWindow.GetTest(uc);
编辑:您也可以在UserControl1或任何其他类中定义属性,并且由于它是附加属性,因此该类甚至不必从DependencyObject派生。
答案 1 :(得分:1)
您似乎可能误解了继承的含义。如果在控件上设置依赖项属性,则该属性的值在其内部的控件中将是相同的。您不需要重新声明属性本身(这只会创建另一个完全不同的属性)。
继承的一个例子:
<Window ...
xmlns:local="..."
local:MainWindow.Test="Lorem Ipsum">
<Button Name="button"/>
在代码中,您应该能够获得按钮上的值,它应该与窗口上的值相同。
var test = (string)button.GetValue(MainWindow.TestProperty);
// test should be "Lorem Ipsum".