c# - 做编译绑定(bind)(x :Bind) require the ViewModel to derive from DependencyObject?

标签 c# xaml mvvm uwp catel

我正在尝试在使用 Catel MVVM 框架实现的项目上使用编译绑定(bind)(应该没关系)。然而,在生成的代码中,我得到编译器错误,因为我的 ViewModel 没有实现通常由 DependencyObjects 公开的某些函数:

CS1061 'MainViewModel' does not contain a definition for 'RegisterPropertyChangedCallback' and no extension method 'RegisterPropertyChangedCallback' accepting a first argument of type 'MainViewModel' could be found (are you missing a using directive or an assembly reference?)



还:

CS0039 Cannot convert type 'Windows.UI.Xaml.DependencyObject' to 'CatelCompiledBindingTest.ViewModels.MainViewModel' via a reference conversion, boxing conversion, unboxing conversion, wrapping conversion, or null type conversion


x:Bind引发错误的编译器生成的代码如下:
public void DependencyPropertyChanged_VM_Visible(global::Windows.UI.Xaml.DependencyObject sender, global::Windows.UI.Xaml.DependencyProperty prop)
{
    MainView_obj1_Bindings bindings = TryGetBindingObject();
    if (bindings != null)
    {
        global::CatelCompiledBindingTest.ViewModels.MainViewModel obj = sender as global::CatelCompiledBindingTest.ViewModels.MainViewModel;
        if (obj != null)
        {
            bindings.Update_VM_Visible(obj.Visible, DATA_CHANGED);
        }
    }
}
private global::CatelCompiledBindingTest.ViewModels.MainViewModel cache_VM = null;
private long tokenDPC_VM_Visible = 0;
public void UpdateChildListeners_VM(global::CatelCompiledBindingTest.ViewModels.MainViewModel obj)
{
    if (obj != cache_VM)
    {
        if (cache_VM != null)
        {
            ((global::System.ComponentModel.INotifyPropertyChanged)cache_VM).PropertyChanged -= PropertyChanged_VM;
            cache_VM.UnregisterPropertyChangedCallback(global::CatelCompiledBindingTest.ViewModels.MainViewModel.VisibleProperty, tokenDPC_VM_Visible);
            cache_VM = null;
        }
        if (obj != null)
        {
            cache_VM = obj;
            ((global::System.ComponentModel.INotifyPropertyChanged)obj).PropertyChanged += PropertyChanged_VM;
            tokenDPC_VM_Visible = obj.RegisterPropertyChangedCallback(global::CatelCompiledBindingTest.ViewModels.MainViewModel.VisibleProperty, DependencyPropertyChanged_VM_Visible);
        }
    }
}

MainViewModel 相当简单(不包括 Catel 样板代码):
public class MainViewModel : ViewModelBase
{
    public MainViewModel()
    {
        ToggleVisibility = new Command(OnToggleVisibilityExecute);
        AddText = new Command(OnAddTextExecute);
        SomeText = "";
    }

    //ViewModel properties

    public string SomeText
    {
        get { return GetValue<string>(SometextProperty); }
        set { SetValue(SometextProperty, value); }
    }

    public bool Visible
    {
        get { return GetValue<bool>(VisibleProperty); }
        set { SetValue(VisibleProperty, value); }
    }

    //ViewModel Commands

    public Command ToggleVisibility { get; private set; }

    public void OnToggleVisibilityExecute()
    {
        Visible = !Visible;
    }

    public Command AddText { get; private set; }

    public void OnAddTextExecute()
    {
        SomeText += "Random text! ";
    }
}

View 如下:
<controls:Page
    x:Class="CatelCompiledBindingTest.Views.MainView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:CatelCompiledBindingTest.Views"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:controls="using:Catel.Windows.Controls"
    xmlns:converters="using:Catel.MVVM.Converters"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Page.Resources>
        <converters:BooleanToCollapsingVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
    </Page.Resources>

    <Grid>
        <Grid.KeyboardAccelerators>
            <KeyboardAccelerator Invoked="{x:Bind VM.OnToggleVisibilityExecute}" Key="T" Modifiers="Control"/>
            <KeyboardAccelerator Invoked="{x:Bind VM.OnAddTextExecute}" Key="Add" Modifiers="Control"/>
        </Grid.KeyboardAccelerators>

        <Border Width="500" Height="500" Visibility="{x:Bind VM.Visible, Mode=OneWay}" Background="SlateGray">
            <TextBlock Style="{ThemeResource HeaderTextBlockStyle}" Text="{x:Bind VM.SomeText, Mode=OneWay}"/>
        </Border>

    </Grid>
</controls:Page>

使用以下代码隐藏能够使用已编译的绑定(bind):
public sealed partial class MainView : Page
{
    public MainView()
    {
        this.InitializeComponent();
        VM = DataContext as MainViewModel;
    }

    public MainViewModel VM { get; set; }
}

现在的问题是:为什么编译器假定 MainViewModel 的类型为 DependencyObject在编译器生成的DependencyPropertyChanged_VM_Visible ?根据Data Binding in Depth ViewModel 只需要实现 IPropertyChanged它确实如此。

我该如何解决这个问题(除了再次求助 {Binding})?我需要在 ViewModel 中包含哪些命名空间才能使编译的 Bindings 工作?

最佳答案

它假定它是一个依赖属性,因为 VM属性在 View MainView 上声明.您应该定义 VM属性作为依赖属性,因此可以绑定(bind)到(所以不是属性的值/类型,而是属性本身)。

关于c# - 做编译绑定(bind)(x :Bind) require the ViewModel to derive from DependencyObject?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51881013/

相关文章:

c# - TimeoutException、TaskCanceledException C#

WPF - 路径几何......有没有办法绑定(bind)数据属性?

c# - 调度线程饱和 - 寻找普通 MVVM 的设计模式变更

c# - 如何访问另一个类中的属性?

c# - 减少具有不同嵌套类的两个类中的代码重复

c# - 如何计算只有起点和终点的贝塞尔曲线?

wpf - 如何使用DynamicDataDisplay在wpf中的一个x-y平面中添加多个图形

c# - 如何在 MVVM 模式中正确实现模型和 View 模型

c# - 如何定义可以返回 DataTable 或 List <T> 的方法?

c# - 重用 XAML block 的最佳方法是什么?