坐落在XAML依赖属性,当基类是通用的坐落在、属性、XAML、基类是

2023-09-07 12:36:19 作者:自然卷的气质;

按照真正的冠军,你怎么能在XAML中设置一个依赖属性,当基类是通用的?当试图做到这一点,我得到一个NullReferenceException,从code设置属性后面工作正常。它也可以当基类是不通用的。 我使用.NET4

下面是一些示例code证明:

WindowBase.cs

 使用System.Windows;

命名空间GenericDependencyPropertyTest
{
    公共类WindowBase<视图模型> : 窗口
    {
        公共静态只读的DependencyProperty HeaderProperty = DependencyProperty.Register(
        头的typeof(串)的typeof(WindowBase<视图模型>),新PropertyMetadata(无头名分配));

        公共字符串标题
        {
            {返回(串)的GetValue(HeaderProperty); }
            保护套{的SetValue(HeaderProperty,价值); }
        }
        受保护的虚拟视图模型型号{获得;组; }
    }
}
 

MainWindow.xaml

 <地方:WindowBase X:类=GenericDependencyPropertyTest.MainWindow
        的xmlns =htt​​p://schemas.microsoft.com/winfx/2006/xaml/$p$psentation
        的xmlns:X =htt​​p://schemas.microsoft.com/winfx/2006/xaml
        XMLNS:地方=CLR的命名空间:GenericDependencyPropertyTest
        X:TypeArguments =本地:IMyViewModel
        标题=主窗口高度=350宽度=525标题=测试>
    <电网>

    < /网格>
< /地方:WindowBase>
 
XAML的属性

MainWindow.xaml.cs

 命名空间GenericDependencyPropertyTest
{
    ///<总结>
    ///为MainWindow.xaml交互逻辑
    ///< /总结>
    公共部分类主窗口:WindowBase< IMyViewModel>
    {
        公共主窗口()
        {
            的InitializeComponent();
        }

        保护覆盖IMyViewModel型号
        {
            得到
            {
                返回base.Model;
            }
            组
            {
                base.Model =价值;
            }
        }
    }
}
 

IMyViewModel.cs

 命名空间GenericDependencyPropertyTest
{
    公共接口IMyViewModel
    {
    }
}
 

解决方案

我的猜测是,问题在于依赖属性(typeof运算(WindowBase&LT的所有者类型;视图模型>)每个封闭泛型类型将是一个完全不同。运行时类型因此而编译器的是高兴的属性存在的WPF运行时无法找到它时,它的外观属性反对的(不同的)请在它的内部存储空间。

当你找到了,非通用类的工作,因为所有者类型和运行时类型是相同的。

您可以得到你想要通过推动移民到非通用基的行为,但仍然得到你的意见,从一个普通的类来获取强类型的模型

 公共类WindowBase:窗口
{
    公共静态只读的DependencyProperty HeaderProperty = DependencyProperty.Register(
        头的typeof(串)的typeof(WindowBase),新PropertyMetadata(无头名分配));

    公共字符串标题
    {
        {返回(串)的GetValue(HeaderProperty); }
        保护套{的SetValue(HeaderProperty,价值); }
    }
}

公共类WindowBase<视图模型> :WindowBase
{
    受保护的视图模型型号{获得;组; }
}
 

As per the title really, how can you set a dependency property in XAML when the base class is generic? When trying to do this I get a NullReferenceException, setting the property from code behind works fine. It also works when the base class is not generic. I'm using .NET4

Here is some sample code to demonstrate:

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
    {
    }
}

解决方案

My guess is that the problem lies with the owner type of the dependency property (typeof(WindowBase<ViewModel>). Each closed generic type will be a completely different runtime type so while the compiler is happy that the property exists the WPF runtime can't find it when it looks the property up against the (different) type in its internal storage.

As you found, the non-generic class works because the owner type and the runtime type are the same.

You can get the behaviour you want by pushing the DPs to a non-generic base but still derive your views from a generic class to get the strongly typed models

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; }
}