【发布时间】:2020-11-12 11:06:14
【问题描述】:
我有一个 ViewModel,其中包含我在每个子 ViewModel 中需要的所有属性。 这是我第一次尝试将命令和视图模型拆分为多个文件。上次一切都在同一个 ViewModel 中,使用它很痛苦。一切都按预期显示,但我想找到一种方法在每个视图模型中传递相同的数据。
从我的 GetOrdersCommand 中,我想获取 HeaderViewModel.SelectedSource 属性。如果没有返回空值或丢失属性数据,我没有找到任何方法...... 我也想从 HeaderView 按钮调用我的 GetOrdersCommand。
任何提示我可以如何做到这一点?也许,我的设计不适合我想做的事情?
MainWindow.xaml
<views:HeaderView Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="2" DataContext="{Binding HeaderViewModel}" LoadHeaderViewCommand="{Binding LoadHeaderViewCommand}"/>
<TabControl TabStripPlacement="Bottom" Grid.Row="1" Grid.Column="1" Grid.RowSpan="2" Grid.ColumnSpan="2">
<TabItem Header="General">
</TabItem>
<TabItem Header="Orders">
<views:OrderView DataContext="{Binding OrderViewModel}" GetOrdersCommand="{Binding GetOrdersCommand}"/>
</TabItem>
</TabControl>
HeaderView.xaml
<DockPanel>
<ComboBox DockPanel.Dock="Left" Width="120" Margin="4" VerticalContentAlignment="Center" ItemsSource="{Binding SourceList}" SelectedItem="{Binding SelectedSource}" DisplayMemberPath="SourceName"/>
<Button x:Name="btnTest" HorizontalAlignment="Left" DockPanel.Dock="Left" Margin="4" Content="Test"/>
</DockPanel>
HeaderView.xaml.cs
public partial class OrderView : UserControl
{
public ICommand GetOrdersCommand
{
get { return (ICommand)GetValue(GetOrdersCommandProperty); }
set { SetValue(GetOrdersCommandProperty, value); }
}
public static readonly DependencyProperty GetOrdersCommandProperty =
DependencyProperty.Register("GetOrdersCommand", typeof(ICommand), typeof(OrderView), new PropertyMetadata(null));
public OrderView()
{
InitializeComponent();
}
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
if (GetOrdersCommand != null)
{
GetOrdersCommand.Execute(this);
}
}
}
MainViewModel.cs
private OrderViewModel orderViewModel;
public OrderViewModel OrderViewModel { get; set; } // Getter, setter with OnPropertyChanged
private HeaderViewModel headerViewModel;
public HeaderViewModel HeaderViewModel { get; set; } // Getter, setter with OnPropertyChanged
public MainViewModel()
{
HeaderViewModel = new HeaderViewModel();
OrderViewModel = new OrderViewModel();
}
HeaderViewModel.cs
public ICommand LoadHeaderViewCommand { get; set; }
public HeaderViewModel()
{
LoadHeaderViewCommand = new LoadHeaderViewCommand(this);
}
GetOrdersCommand.cs
public class GetOrdersCommand : ICommand
{
public event EventHandler CanExecuteChanged;
private readonly OrderViewModel _orderViewModel;
public GetOrdersCommand(OrderViewModel orderViewModel)
{
_orderViewModel = orderViewModel;
}
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
/* Build Order List according to HeaderViewModel.SelectedSource */
_orderViewModel.Orders = new ObservableCollection<Order>()
{
new Order { ID = 1, IsReleased = false, Name = "Test1"},
new Order { ID = 2, IsReleased = true, Name = "Test2"},
};
}
}
【问题讨论】:
-
对我来说,GetOrdersCommand 类并在 OrderVM 中为其创建 DP 比它应该的要复杂一些。怎么样,在 HeaderVM 中注入 OrderVM。并编辑 HeaderVM.SelectedSource 的 setter 以更新 OrderVM 中的相关信息。
-
您应该使用 prism delegatecommand 或(最好)mvvmlight relaycommand 并在其拥有的视图模型中定义命令。这使您的视图模型更易于理解,并且您可以在命令中捕获变量。
-
GetOrdersCommand.cs .... 糟糕的代码!更好的是使用在构造函数中接受方法的通用 ICommand 接口实现。初始化命令时,将所需的方法传递给它。
-
我应该看到 OrderViewModel 类的源代码。
-
HeaderViewModel.SelectedSource 必须作为命令参数传递。
标签: c# wpf mvvm data-binding icommand