在XAML中设置依赖属性当基类是泛型的时候

6

根据标题,当基类是泛型时,如何在XAML中设置依赖属性?尝试这样做时,我会得到NullReferenceException,从代码后台设置属性可以正常工作。当基类不是泛型时,它也可以正常工作。

我正在使用.NET4

以下是一些示例代码:

WindowBase.cs

using System.Windows;

namespace GenericDependencyPropertyTest
{
    public class WindowBase<ViewModel> : Window
    {
        public static readonly DependencyProperty HeaderProperty = DependencyProperty.Register(
        "Header", typeof(string), typeof(WindowBase<ViewModel>), new PropertyMetadata("No Header Name Assigned"));

        public string Header
        {
            get { return (string)GetValue(HeaderProperty); }
            protected set { SetValue(HeaderProperty, value); }
        }
        protected virtual ViewModel Model { get; set; }
    }
}

MainWindow.xaml

<local:WindowBase x:Class="GenericDependencyPropertyTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:GenericDependencyPropertyTest"
        x:TypeArguments="local:IMyViewModel"
        Title="MainWindow" Height="350" Width="525" Header="Test">
    <Grid>

    </Grid>
</local:WindowBase>

MainWindow.xaml.cs

namespace GenericDependencyPropertyTest
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : WindowBase<IMyViewModel>
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        protected override IMyViewModel Model
        {
            get
            {
                return base.Model;
            }
            set
            {
                base.Model = value;
            }
        }
    }
}

IMyViewModel.cs

namespace GenericDependencyPropertyTest
{
    public interface IMyViewModel
    {
    }
}

“当基类是泛型时”是什么意思?你是指自定义控件吗? - Prince Ashitaka
抱歉表述不够清晰。我的意思是一个控件(或窗口,在这种情况下)继承自一个通用类,在我上面的示例中,我传递了一个接口作为窗口将拥有的视图模型类型的MainWindow从WindowBase继承。 - ChrisWay
1个回答

8
我的猜测是问题出在依赖属性的所有者类型上 (typeof(WindowBase<ViewModel>)。每个封闭的泛型类型将是一个完全不同的运行时类型,因此,虽然编译器知道属性存在,但 WPF 运行时在其内部存储中查找该属性时找不到它(因为它是根据不同的类型查找的)。
就像你发现的那样,非泛型类有效,因为所有者类型和运行时类型相同。
您可以通过将 DP 推送到非泛型基类中来获得所需的行为,但仍从泛型类派生您的视图以获取强类型模型。
public class WindowBase : Window
{
    public static readonly DependencyProperty HeaderProperty = DependencyProperty.Register(
        "Header", typeof(string), typeof(WindowBase), new PropertyMetadata("No Header Name Assigned"));

    public string Header
    {
        get { return (string)GetValue(HeaderProperty); }
        protected set { SetValue(HeaderProperty, value); }
    }
}

public class WindowBase<ViewModel> : WindowBase
{
    protected ViewModel Model { get; set; }
}

1
现在已经是2018年了,这对我帮助很大。将来我会用泛型的方式来处理所有的课程。我想你们都已经迈向更高更好的事物了! - miriyo
@miriyo 很高兴听到该网站在作为历史知识库方面发挥了其作用!即使我们大多已经从WPF过渡,但静态范围在泛型类中的作用并没有改变。 - JRoughan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接