如何使用mvvm模式从不同的ViewModel获取属性和调用命令

我有一个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"},};
        }
    }
iCMS 回答:如何使用mvvm模式从不同的ViewModel获取属性和调用命令

谢谢大家!我按照建议将命令移到了它们自己的ViewModel中。 我尝试了MVVVM Light Tools,并发现了有关Messenger类的信息。

我用它将我的SelectedSource(HeaderView中的组合框)从HeaderViewModel发送到OrderViewModel。我想使用这样的Messenger类吗?我不知道,但是成功了!!!

我曾考虑过将GetOrdersCommand移至OrderViewModel,将按钮命令绑定至OrderViewModel,将SelectedSource绑定为CommandParameter,但是当HeaderViewModel.SelectedSource更改时,我不知道我应该如何设置RaiseCanExecuteChanged ...有什么建议吗?

MainWindow.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

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" }
        };
    }
}

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;
}
本文链接:https://www.f2er.com/1883681.html

大家都在问