【问题标题】:How can i bind to the sub-ViewModel using ViewModel inheritance?如何使用 ViewModel 继承绑定到子 ViewModel?
【发布时间】:2020-04-17 12:10:06
【问题描述】:

在我的应用程序中,我有以下 MasterViewModel1-class。

public class MasterViewModel1 : ViewModelBase
{
    private ObservableCollection<ObservableObject> _MainGrid;

    public ObservableCollection<ObservableObject> MainGrid
    {
        get => _MainGrid;
        set
        {
            _MainGrid = value;
            RaisePropertyChanged();
        }
    }

    public ObservableCollection<FilterItem> FilterItems
    {
        get;
        set;
    }

    public MasterViewModel1()
    {
        CreateDefaultMenu();
    }

    public void CreateDefaultMenu()
    {
        FilterItems = new ObservableCollection<FilterItem>
        {
            new FilterItem(OnFilterClicked)
            {
                Content = "Filter"
            },
            new FilterItem(OnFilterCancelClicked)
            {
                Content = "Filter aufheben"
            }
        };
    }

    public virtual void OnFilterClicked() { }
    public virtual void OnFilterCancelClicked() { }

MasterViewModel1 类由 TestViewModel 类继承。

public class TestViewModel : MasterViewModel1
{
    private Kunde _NeuerKunde;
    public Kunde NeuerKunde
    {
        get => _NeuerKunde;
        set => _NeuerKunde = value;
    }

    private string _Kundenmatchcode;
    public string Kundenmatchcode
    {
        get => _Kundenmatchcode;
        set
        {
            _Kundenmatchcode = value;
            RaisePropertyChanged();
        }
    }

    public TestViewModel()
    {
        NeuerKunde = new Kunde();
    }
}

出于可重用的原因,我使用 MasterViewModel1 类及其视图,因为将来会有更多的视图继承 MasterViewModel。

在需要绑定到 MasterViewModel 的 MasterView 内部,所以我有“Base-Design”。 我需要绑定到“Sub”ViewModel,在这个例子中是 TestViewModel。

View of the MasterViewModel1

在图片中您可以看到 MasterView。红色标记的区域是应该放置TestViewModel(TestView)的地方。我不能使用静态资源!!!它必须是动态的,所以如果我实例化另一个 ViewModel,它也继承自 MasterViewModel1。红色标记的区域应根据实例化的 ViewModel 发生变化。

我希望它足够清楚。 如果您需要更多信息,请询问。

【问题讨论】:

  • 您没有显示 xaml,问题也没有解释您究竟绑定了什么。什么是“基础设计”?红色区域显示什么以及何时应该更改?见minimal reproducible example
  • 通常,超类的所有公共属性都是可见的,并且可以通过每个子类访问。您可以绑定到每个公共属性。如果您想根据实际实现或类型更改视图的布局或外观,您应该使用DataTemplate,它描述了视图的结构和绑定到模型数据的方式。

标签: c# wpf mvvm binding viewmodel


【解决方案1】:

通常,超类的所有公共属性都可以通过每个子类可见和访问。您可以绑定到每个公共属性。

如果您想根据实际实现或类型更改视图的布局或外观,您应该使用DataTemplate,它描述了视图的结构以及与模型数据的绑定方式。
一个简单的ContentControl 将作为动态视图宿主。

ViewModelBase.cs

public class ViewModelBase : INotifyPropertyChanged
{    
  public event PropertyChangedEventHandler PropertyChanged;
  protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
  {
    this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
  }
}

MainViewModel.cs

public class MainViewModel : ViewModelBase 
{   
  private ViewModelBase currentView;   
  public ViewModelBase CurrentView
  {
    get => this.currentView;
    set 
    { 
      this.currentView= value; 
      OnPropertyChanged();
    }
  }

  public ICommand ToggleViewCommand => new RelayCommand(param => this.CurrentView = this.Views.FirstOrDefault(view => view != this.CurrentView));

  private List<ViewModelBase> Views { get; }

  public MainViewModel()
  {
    this.Views = new ObservableCollection<ViewModelBase>()
    {
      new TestViewModel() { Value = "TestViewModel View" },
      new AnotherTestViewModel() { Name = "AnotherTestViewModel View" }
    }

    this.CurrentView = this.Views.First();
  }
}

TestViewModel.cs

public class TestViewModel : ViewModelBase
{
  private string value;   
  public string Value
  {
    get => this.value;
    set 
    { 
      this.value = value; 
      OnPropertyChanged();
    }
  }
}

AnotherTestViewModel.cs

public class TestViewModel : ViewModelBase
{
  private string name;   
  public string Name
  {
    get => this.name;
    set 
    { 
      this.name = value; 
      OnPropertyChanged();
    }
  }
}

TestView.xaml

<Window>
  <Window.DataContext>
    <TestViewModel />
  </Window.DataContext>

  <TextBlock Text="{Binding Value}" />
</Window>

MainWindow.xaml

<Window>
  <Window.DataContext>
    <MainViewModel />
  </Window.DataContext>

  <Window.Resources>

    <!-- Define the views as an implicit (keyless) DataTemplate -->
    <DataTemplate DataType="{x:Type TestViewModel}">

      <!-- Show a view as a UserControl -->
      <TestView />
    </DataTemplate>

    <DataTemplate DataType="{x:Type AnotherTestViewModel}">

      <!-- Or add a elements -->
      <StackPanel Orientation="Horizontal">
        <TextBlock Text="{Binding Name}" />
        <Rectangle Height="80" Width="80" Fill="Red" />
      </StackPanel>
    </DataTemplate>
  </Window.Resources>

  <StackPanel>
    <Button Command="{Binding ToggleViewCommand}" Content="Toggle View" />

    <!-- 
      Host of the different views based on the actual model type (dynamic view).
      The implicit DataTemplates will apply automatically
      and show the view that maps to the current CurrentView view model type
    -->
    <ContentControl Content="{Binding CurrentView}" />
  </StackPanel>
</Window>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-07
    • 1970-01-01
    • 2011-08-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多