使用RelayCommand导航

时间:2015-12-10 13:10:31

标签: c# mvvm

我正在使用MVVM开发第一个应用程序。我跟着this link for navigation。在 Lawrence A. Contreras 的回答中,我使用了第一种导航方法,但是我收到了Command not found错误。我的代码是

<ListView x:Name="lstItem" Grid.Row="1" ItemsSource="{Binding OrdersObject.data.orders}" ItemTemplate="{StaticResource DueOrderTemplate}" ItemContainerStyle="{StaticResource StretchItemStyle}">
        <Interactivity:Interaction.Behaviors>
            <Core:EventTriggerBehavior EventName="SelectionChanged">
                <Core:InvokeCommandAction CommandParameter="{Binding SelectedItem, ElementName=lstItem}" Command="{Binding SelectedOrderCommand}"/>
            </Core:EventTriggerBehavior>
        </Interactivity:Interaction.Behaviors>
    </ListView>

和cs是

var OrdersObj = new ViewModels.OrdersVM();
            OrdersObj.SelectedOrderCommand = new RelayCommand<Models.OOrderM>((itemParam) =>
            {
                if (itemParam != null)
                    this.Frame.Navigate(typeof(OrderEditP), itemParam);
            });
                        await OrdersObj.GetOrders("pending");

            this.DataContext = OrdersObj;

我的视图模型是

    class OrdersVM
{
        RelayCommand<OOrderM> _slectedOrderCommand;
        public RelayCommand<OOrderM> SelectedOrderCommand;
}

我犯错误的地方?我没有使用任何图书馆,也不想这样做,所以我试图避免实施INAVigation服务。所以,如果不可能这样,我会欢迎任何其他建议。

我收到的错误是

BindingExpression路径错误:&#39; SelectedOrderCommand&#39;在App.ViewModels.OrdersVM,App,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null&#39;上找不到属性。 BindingExpression:Path =&#39; SelectedOrderCommand&#39; DataItem =&#39; App.ViewModels.OrdersVM,ShopkeeperApp,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null&#39 ;;目标元素是&#39; Microsoft.Xaml.Interactions.Core.InvokeCommandAction&#39; (名称=&#39;空&#39);目标财产是&#39; Command&#39; (键入&#39; ICommand&#39;)

2 个答案:

答案 0 :(得分:0)

我假设您有一个包含订单列表的页面,当您从该列表中选择时,您希望导航到订单详细信息页面。

我在您的示例中看到您对SelectionChanged事件使用了EventtriggerBehavior。这是有效的,但是处理选择的更好方法已经改变了。我宁愿将属性绑定到ListView的 SelectedValue

<ListView x:Name="lstItem" Grid.Row="1" ItemsSource="{Binding OrdersObject.data.orders}" ItemTemplate="{StaticResource DueOrderTemplate}" ItemContainerStyle="{StaticResource StretchItemStyle}" SelectedValue="{Binding SelectedOrder, UpdateSourcetrigger=PropertyChanged, Mode=TwoWay}">

现在在VM上,我假设你的项目是&#34; Order&#34;类。为简单起见,我将使用一个动作,我们将调用_NavigateAction以允许视图模型在需要时进行导航。您需要将该操作传递给viewmodel的构造函数。

  public class OrdersVM : ViewModelBase
  {
    private Action<Order> _NavigateToOrderAction;

    private Order _SelectedOrder;

    public OrdersVM(Action<Order> navigateToOrderAction)
    {
      PropertyChanged += OrdersVM_PropertyChanged;
    }

    public Order SelectedOrder
    {
      get
      {
        return _SelectedOrder;
      }
      set
      {
        _SelectedOrder = value;
        OnPropertyChanged("SelectedOrder");
      }
    }

    private void OrdersVM_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
      if (e.PropertyName == "SelectedOrder")
        OnSelectedOrderChanged();
    }

    private void OnSelectedOrderChanged()
    {
      //Use Selected order and do something.
      _NavigateToOrderAction(SelectedOrder);
    }
  }

您可能想知道我订阅了 PropertyChanged 事件,而不是在SelectedOrder的setter中调用 OnSelectedOrderChanged()。原因在于,如果您打算调用异步方法,则无法在setter中执行此操作。如果您在 OrdersVM_PropertyChanged 中,则可以轻松地将其设为异步功能。

让我们回到后面的代码。我们将实例化传递操作的viewmodel。在这里,我们将首先定义操作将执行的操作。我们希望它导航到OrderDetailsPage,我们希望将所选顺序作为导航参数传递。

  public sealed partial class MainPage : Page
  {
    public MainPage()
    {
      this.InitializeComponent();

      Action<Order> navigateToOrderAction = order =>
      {
        this.Frame.Navigate(typeof(OrderDetailsPage), order);
      };

      OrdersVM orderVM = new OrdersVM(navigateToOrderAction);
      this.DataContext = orderVM;
    }
  }

现在,在 OrderDetails 代码后面,您可以覆盖OnNavigateTo方法并获取从上一页传递的订单实例。

  public sealed partial class OrderDetailsPage : Page
  {
    public OrderDetailsPage()
    {
      this.InitializeComponent();
    }

    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
      Order selectedOrder = e.Content as Order;
      if (selectedOrder != null)
      { //Do something with the selected order
        this.DataContext = selectedOrder;
      }
      base.OnNavigatedTo(e);
    }
  }

答案 1 :(得分:-1)

我通过在ViewModel中创建一个Frame类型的属性来解决这个问题,该属性返回当前帧。所以我能够根据需要导航和执行操作,也允许我分离代码。

Frame currentFrame{get{return Window.Current.Content as Frame;}}



   public RelayCommand<OOrderM> SelectedOrderCommand{
get
    {
return _slectedOrderCommand??new RelayCommand<object>((itemParam)=>
{
    currentFrame.Navigate(typeof(myPage));
})
};
}
相关问题