使用RelayCommand进行导航
本文关键字:导航 RelayCommand 使用 | 更新日期: 2023-09-27 18:26:17
我正在使用MVVM开发第一个应用程序。我已通过此链接进行导航。Lawrence A.Contreras的回答是,我使用了第一种导航方法,但我收到了未发现错误的命令。我的代码是
<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;
}
我在哪里犯错误?我没有使用任何库,也不想使用,所以我尽量避免实现导航服务。因此,如果这样做不可能,我将欢迎任何其他建议。
我收到的错误是
BindingExpression路径错误:在"App.ViewModels.OrdersVM,App,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null"上找不到"SelectedOrderCommand"属性。BindingExpression:Path='SelectedOrderCommand'DataItem='App.ViewModels.OrdersVM,ShopkeeperApp,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null';目标元素是"Microsoft.Xaml.Interactions.Core.InvokeCommandAction"(名称="ull");目标属性为"Command"(类型为"ICommand")
我假设您有一个包含订单列表的页面,当您从该列表中进行选择时,您希望导航到订单详细信息页面。
在您的示例中,我看到您对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上,我假设您的项目是"Order"类的一个实例。为了简单起见,我将只使用一个操作,我们将调用该操作_NavigateAction,以允许视图模型在需要时进行导航。您需要将该操作传递给视图模型的构造函数。
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中,您可以轻松地将其设置为异步函数。
让我们看看后面的代码。我们将实例化传入动作的视图模型。在这里,我们将首先定义操作要做什么。我们希望它导航到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);
}
}
我通过在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));
})
};
}