在 UI 中显示来自 ViewModel 的控件
Show Control from ViewModel in UI
我的 ViewModel 中有一个 UserControl,需要根据 ViewModel 的上下文进行更改。
例如:我的 ViewModel 包含一个枚举。当此枚举的值为 Test1
时,CurrentView 属性 将更改为类型 MyCustomTest1
的对象。当值为 Test2
时,属性 成为 MyCustomTest2
的对象。我已经知道如何实现它,但不知道如何告诉我的 UI 呈现 CustomControl。
我想我需要为此使用 ItemsControl,但我不确定。这是我到目前为止尝试过的。
<StackPanel x:Name="MainContent" Grid.Column="1">
<ItemsControl ItemsSource="{Binding CurrentView, Mode=OneWay}" />
</StackPanel>
我的自定义组件只包含一个带有 TextBlock 的 StackPanel。
MyCustomTest1:
<StackPanel>
<TextBlock>Hello World</TextBlock>
</StackPanel>
我的 ViewModel 在更新 CurrentView 时调用 INotifyPropertyChanged。
public UserControl CurrentView
{
get => currentView;
private set
{
currentView = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(CurrentView)));
}
}
有人知道如何实现吗?
您可以设计一个 ValueConverter,例如:
using System;
using System.Globalization;
using System.Windows.Data;
public class MyValueConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if(value is ControlType type)
{
if (type == ControlType.Type1)
return new MyCustomTest1();
else if (type == ControlType.Type2)
return new MyCustomTest2();
}
throw new NotImplementedException();
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
然后你可以添加一个ContentControl
,并将其Content
绑定到枚举属性,并引入转换器:
<UserControl.Resources>
<!-- vc is the namespace where you put the value converter class -->
<vc:MyValueConverter x:Key="converter" />
</UserControl.Resources>
...
<ContentControl Content="{Binding CurrentView, Converter={StaticResource converter}}" />
视图模型绝不能知道任何控件。控件仅在视图中处理。
您的问题通常通过使用数据模型和关联的 DataTemplated
来解决,它指示视图如何呈现数据模型。
这意味着您应该为每个视图引入一个数据模型。然后将这个模型绑定到一个ContentControl
。然后 ContentControl
将应用 DataTemplate
作为模型的数据类型,然后将呈现视图。
MainViewModel.cs
class MainViewModel : INotifyPropertyChanged
{
// TODO::Let this property raise the PropertyChanged event
public object CurrentViewModel { get; set; }
private void LoadView()
{
this.CurrentView = new MyCustomControlViewModel();
}
}
MainWindow.xaml
<Window>
<Window.DataContext>
<MainViewModel />
</Window.Resources>
<Window.Resources>
<DataTemplate DataType="{x:Type MyCustomControlViewModel}">
<MyCustomControl />
</DataTemplate>
</Window.Resources>
<ContentControl Content="{Binding CurrentViewModel}" />
</Window>
我的 ViewModel 中有一个 UserControl,需要根据 ViewModel 的上下文进行更改。
例如:我的 ViewModel 包含一个枚举。当此枚举的值为 Test1
时,CurrentView 属性 将更改为类型 MyCustomTest1
的对象。当值为 Test2
时,属性 成为 MyCustomTest2
的对象。我已经知道如何实现它,但不知道如何告诉我的 UI 呈现 CustomControl。
我想我需要为此使用 ItemsControl,但我不确定。这是我到目前为止尝试过的。
<StackPanel x:Name="MainContent" Grid.Column="1">
<ItemsControl ItemsSource="{Binding CurrentView, Mode=OneWay}" />
</StackPanel>
我的自定义组件只包含一个带有 TextBlock 的 StackPanel。
MyCustomTest1:
<StackPanel>
<TextBlock>Hello World</TextBlock>
</StackPanel>
我的 ViewModel 在更新 CurrentView 时调用 INotifyPropertyChanged。
public UserControl CurrentView
{
get => currentView;
private set
{
currentView = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(CurrentView)));
}
}
有人知道如何实现吗?
您可以设计一个 ValueConverter,例如:
using System;
using System.Globalization;
using System.Windows.Data;
public class MyValueConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if(value is ControlType type)
{
if (type == ControlType.Type1)
return new MyCustomTest1();
else if (type == ControlType.Type2)
return new MyCustomTest2();
}
throw new NotImplementedException();
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
然后你可以添加一个ContentControl
,并将其Content
绑定到枚举属性,并引入转换器:
<UserControl.Resources>
<!-- vc is the namespace where you put the value converter class -->
<vc:MyValueConverter x:Key="converter" />
</UserControl.Resources>
...
<ContentControl Content="{Binding CurrentView, Converter={StaticResource converter}}" />
视图模型绝不能知道任何控件。控件仅在视图中处理。
您的问题通常通过使用数据模型和关联的 DataTemplated
来解决,它指示视图如何呈现数据模型。
这意味着您应该为每个视图引入一个数据模型。然后将这个模型绑定到一个ContentControl
。然后 ContentControl
将应用 DataTemplate
作为模型的数据类型,然后将呈现视图。
MainViewModel.cs
class MainViewModel : INotifyPropertyChanged
{
// TODO::Let this property raise the PropertyChanged event
public object CurrentViewModel { get; set; }
private void LoadView()
{
this.CurrentView = new MyCustomControlViewModel();
}
}
MainWindow.xaml
<Window>
<Window.DataContext>
<MainViewModel />
</Window.Resources>
<Window.Resources>
<DataTemplate DataType="{x:Type MyCustomControlViewModel}">
<MyCustomControl />
</DataTemplate>
</Window.Resources>
<ContentControl Content="{Binding CurrentViewModel}" />
</Window>