我正在使用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;)
答案 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));
})
};
}