WPF中如何将绑定自有ViewModel的View与另一个ViewModel属性绑定?
问题需求
现有两个View(HomeView、DashboardView)和对应的ViewModel(HomeViewModel、DashboardViewModel),DashboardViewModel包含status属性,需要在HomeView中绑定该属性。尝试通过DataTemplate关联View与ViewModel,并在HomeView中调用DashboardViewModel的DataContext,但绑定未生效,寻求解决方法或示例。
现有代码
HomeView.xaml
<UserControl x:Class="Demo.View.Home" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:Demo.View" xmlns:viewmodel="clr-namespace:Demo.ViewModel" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"> <Grid Background="BlueViolet"> <Grid.ColumnDefinitions> <ColumnDefinition Width="300"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <CheckBox Content="second" IsChecked="{Binding status}" Margin="200,100,0,0"/> </Grid> </UserControl>
DashboardView.xaml
<UserControl x:Class="Demo.View.Dashboard" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:Demo.View" xmlns:vm="clr-namespace:Demo.ViewModel" xmlns:dt="clr-namespace:DefectTracking;assembly=DefectTrackingControl" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"> <Grid Background="Red"> <StackPanel> <CheckBox Content="one" IsChecked="{Binding status}" Margin="200,100,10,10"/> </StackPanel> </Grid> </UserControl>
HomeViewModel.cs
using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Threading; namespace Demo.ViewModel { public class HomeViewModel : INotifyPropertyChanged { private bool _check; public bool Check { get { return _check; } set { _check = value; } } public event PropertyChangedEventHandler PropertyChanged; private void OnPropertyChanged(string propertyName) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } } }
DashboardViewModel.cs
using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Threading; using DefectTracking; using System.Runtime.CompilerServices; using System.Windows; namespace Demo.ViewModel { public class DashboardViewModel : DependencyObject, INotifyPropertyChanged { public DispatcherTimer DispatchTimer = new DispatcherTimer(); public DashboardViewModel() { DispatchTimer.Interval = TimeSpan.FromMilliseconds(1000); DispatchTimer.Tick += dispatchTimer_Tick; DispatchTimer.Start(); } private bool _status; public bool status { get { return _status; } set { _status = value; OnPropertyChanged(nameof(status)); } } private void dispatchTimer_Tick(object sender, EventArgs e) { status = !status; } public event PropertyChangedEventHandler PropertyChanged; private void OnPropertyChanged(string propertyName) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } } }
解决方法
步骤1:修改HomeViewModel,添加DashboardViewModel实例
HomeView的DataContext是HomeViewModel,要访问DashboardViewModel的status,需让HomeViewModel持有其实例:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Threading; namespace Demo.ViewModel { public class HomeViewModel : INotifyPropertyChanged { private bool _check; // 初始化DashboardViewModel实例 public DashboardViewModel DashboardVM { get; set; } = new DashboardViewModel(); public bool Check { get { return _check; } set { _check = value; OnPropertyChanged(nameof(Check)); } } public event PropertyChangedEventHandler PropertyChanged; private void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } }
步骤2:修正HomeView的绑定路径
绑定需指向HomeViewModel中的DashboardVM.status,而非直接status:
<CheckBox Content="second" IsChecked="{Binding DashboardVM.status}" Margin="200,100,0,0"/>
步骤3:确保View的DataContext正确设置
在HomeView构造函数中设置DataContext:
using System.Windows.Controls; namespace Demo.View { public partial class Home : UserControl { public Home() { InitializeComponent(); DataContext = new ViewModel.HomeViewModel(); } } }
DashboardView同理(若需独立使用):
using System.Windows.Controls; namespace Demo.View { public partial class Dashboard : UserControl { public Dashboard() { InitializeComponent(); DataContext = new ViewModel.DashboardViewModel(); } } }
可选:全局DataTemplate关联View与ViewModel
若希望自动根据ViewModel加载对应View,可在App.xaml中定义DataTemplate:
<Application x:Class="Demo.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:vm="clr-namespace:Demo.ViewModel" xmlns:view="clr-namespace:Demo.View" StartupUri="MainWindow.xaml"> <Application.Resources> <DataTemplate DataType="{x:Type vm:DashboardViewModel}"> <view:Dashboard/> </DataTemplate> <DataTemplate DataType="{x:Type vm:HomeViewModel}"> <view:Home/> </DataTemplate> </Application.Resources> </Application>
后续在容器(如ContentControl)中绑定ViewModel时,会自动加载对应View。
内容的提问来源于stack exchange,提问作者Yasir Ali
相关产品推荐
相关产品推荐

