[英]How to get property and call command from different ViewModel with mvvm pattern
I have a ViewModel with all the properties that i will need in every sub ViewModel.我有一个 ViewModel,其中包含我在每个子 ViewModel 中需要的所有属性。 It's the first time i try to split commands and viewmodel to multiple files.
这是我第一次尝试将命令和视图模型拆分为多个文件。 Last time everything was in the same ViewModel and it was a pain to work with it.
上次一切都在同一个 ViewModel 中,使用它很痛苦。 Everything shows up as expected but i want to find a way to pass the same data in every viewmodel.
一切都按预期显示,但我想找到一种方法在每个视图模型中传递相同的数据。
From my GetOrdersCommand, i want to get the HeaderViewModel.SelectedSource property.从我的 GetOrdersCommand 中,我想获取 HeaderViewModel.SelectedSource 属性。 I didn't find any way to do it without getting a null return or loosing the property data... I would like to call my GetOrdersCommand from HeaderView button too.
如果没有返回 null 或丢失属性数据,我找不到任何方法......我也想从 HeaderView 按钮调用我的 GetOrdersCommand。
Any tips how i can achieve this?有什么提示我可以做到这一点吗? Perhaps, my design is not good for what i'm trying to do?
也许,我的设计不适合我想做的事情?
MainWindow.xaml主窗口.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 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 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主视图模型.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 HeaderViewModel.cs
public ICommand LoadHeaderViewCommand { get; set; }
public HeaderViewModel()
{
LoadHeaderViewCommand = new LoadHeaderViewCommand(this);
}
GetOrdersCommand.cs 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"},
};
}
}
Thanks guys.多谢你们。 I moved my commands to their owning ViewModel as suggested.
我按照建议将我的命令移到了他们拥有的 ViewModel 中。 I tried MVVVM Light Tools and found about Messenger Class.
我尝试了 MVVVM Light Tools 并找到了关于 Messenger Class 的信息。
I used it to send my SelectedSource (Combobox from HeaderView) from HeaderViewModel to OrderViewModel.我用它将我的 SelectedSource(来自 HeaderView 的组合框)从 HeaderViewModel 发送到 OrderViewModel。 Am i suppose to use Messenger class like that?
我想像那样使用 Messenger class 吗? I don't know, but it did the trick!!!
我不知道,但它成功了!!!
I thought about moving GetOrdersCommand to OrderViewModel, binding my button command to OrderViewModel, binding SelectedSource as CommandParameter but i didn't know how i was suppose to RaiseCanExecuteChanged when HeaderViewModel.SelectedSource changed... Any advice?我考虑过将 GetOrdersCommand 移动到 OrderViewModel,将我的按钮命令绑定到 OrderViewModel,将 SelectedSource 绑定为 CommandParameter 但我不知道当 HeaderViewModel.SelectedSource 更改时我应该如何 RaiseCanExecuteChanged ......有什么建议吗?
MainWindow.xaml主窗口.xaml
<views:HeaderView DataContext="{Binding Source={StaticResource Locator}, Path=HeaderVM}" Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="2"/>
<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 Source={StaticResource Locator}, Path=OrderVM}"/>
</TabItem>
</TabControl>
OrderViewModel.cs OrderViewModel.cs
private ObservableCollection<Order> _orders;
public ObservableCollection<Order> Orders
{
get { return _orders; }
set
{
if (_orders != value)
{
_orders = value;
RaisePropertyChanged(nameof(Orders));
}
}
}
public OrderViewModel()
{
Messenger.Default.Register<Source>(this, source => GetOrders(source));
}
private void GetOrders(Source source)
{
if (source.SourceName == "Production")
{
Orders = new ObservableCollection<Order>(){
new Order { ID = 1, IsReleased = false, Name = "Production 1" }
};
}
else
{
Orders = new ObservableCollection<Order>(){
new Order { ID = 2, IsReleased = true, Name = "Test 1" }
};
}
}
Part of HeaderViewModel.cs HeaderViewModel.cs 的一部分
private Source _SelectedSource;
public Source SelectedSource
{
get { return _SelectedSource; }
set
{
if (_SelectedSource != value)
{
_SelectedSource = value;
RaisePropertyChanged(nameof(SelectedSource));
GetOrdersCommand.RaiseCanExecuteChanged();
}
}
}
private RelayCommand _GetOrdersCommand;
public RelayCommand GetOrdersCommand
{
get
{
if (_GetOrdersCommand == null)
{
_GetOrdersCommand = new RelayCommand(GetOrders_Execute, GetOrders_CanExecute);
}
return _GetOrdersCommand;
}
}
private void GetOrders_Execute()
{
Messenger.Default.Send(SelectedSource);
}
private bool GetOrders_CanExecute()
{
return SelectedSource != null ? true : false;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.