拥有一个基类 Window 会带来一个严重的缺点,即绑定到基类中的属性要困难得多(并且当前接受的答案不能解决这个问题)。如果不能引用基本属性,继承有什么意义?经过几个小时后,我想出了如何设置它,并希望与大家分享,希望其他人能够免于这种痛苦。
您可能需要使用值转换器之类的东西,它只能通过静态绑定来引用,在我的情况下,在 WindowBase 类中使用它是有意义的。我提供了一个示例,因为我发现很难在设计和运行模式下一致地使用这些转换器。
您无法通过 XAML 设置此继承窗口的 x:Name 属性,但如果使用以下方法,您可能不需要这样做。我已经包含了一个如何设置名称的示例,因为从 Window 继承将不允许您在设计时在子类中设置名称。我不建议在设计时依赖窗口的名称,但设置 d:DataContext 应该可以满足您的任何绑定需求。
请注意,在设计模式而非运行模式下,WindowBase(或 d:DataContext 中指定的类)的副本将在设计模式下被实例化并用作绑定上下文。因此,在非常具体的情况下,您可能会看到数据差异,但在绝大多数用例中,这种方法就足够了。
WindowBase.cs
````
public class WindowBase : Window
{
//User-Defined UI Configuration class containing System.Drawing.Color
//and Brush properties (platform-agnostic styling in your Project.Core.dll assembly)
public UIStyle UIStyle => Core.UIStyle.Current;
//IValueConverter that converts System.Drawing.Color properties
//into WPF-equivalent Colors and Brushes
//You can skip this if you do not need or did not implement your own ValueConverter
public static IValueConverter UniversalValueConverter { get; } = new UniversalValueConverter();
public WindowBase()
{
//Add window name to scope so that runtime properties can be referenced from XAML
//(Name setting must be done here and not in xaml because this is a base class)
//You probably won't need to, but working example is here in case you do.
var ns = new NameScope();
NameScope.SetNameScope(this, ns);
ns["window"] = this;
//Call Initialize Component via Reflection, so you do not need
//to call InitializeComponent() every time in your base class
this.GetType()
.GetMethod("InitializeComponent",
System.Reflection.BindingFlags.Public |
System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Instance)
.Invoke(this, null);
//Set runtime DataContext - Designer mode will not run this code
this.DataContext = this;
}
//Stub method here so that the above code can find it via reflection
void InitializeComponent() { }
}
SubClassWindow.xaml
<local:WindowBase
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:YourProjectNamespace"
x:Class="YourProjectNamespace.SubClassWindow"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance Type= {x:Type local:WindowBase}, IsDesignTimeCreatable=True}"
Title="SubClassWindow" Height="100" Width="300">
<!--Design-time DataContext is set in d:DataContext. That option does not affect runtime data binding
Replace local:WindowBase with local:SubClassWindow if you need to access properties in SubClassWindow-->
<Grid Background="{Binding UIStyle.BackgroundColor, Converter={x:Static local:WindowBase.UniversalValueConverter}}"></Grid>
</local:WindowBase>
在后面的 SubClassWindow 代码中不需要任何东西(甚至不需要构造函数)。