CaliburnMicro操作不会触发数据模板

问题描述:

我想要创建某种过滤器,当用户从应用程序栏中单击过滤器按钮时,它将启动一个带有列表选择器的弹出页面。我搜索了很多方法,但仍然无法实现。CaliburnMicro操作不会触发数据模板

这里是我的代码:

XAML(MainPageView.xaml)

<phone:PhoneApplicationPage.Resources> 
     <DataTemplate x:Key="PivotContentTemplate"> 
      <phone:Pivot Margin="-12,0,0,0" Title="FOREX NEWS" Height="672"> 
       <phone:PivotItem Header="filter" FontFamily="{StaticResource PhoneFontFamilySemiLight}" FontSize="32"> 
        <StackPanel Margin="12,0,0,0"> 
         <toolkit:ListPicker Header="currencies" SelectionMode="Multiple" 
              micro:Message.Attach="[Event SelectionChanged] = [Action OnCurrenciesChanged($eventArgs)]"> 
          <sys:String>gbp</sys:String> 
          <sys:String>eur</sys:String> 
          <sys:String>usd</sys:String> 
         </toolkit:ListPicker>       
        </StackPanel> 
       </phone:PivotItem> 
      </phone:Pivot> 
     </DataTemplate> 
<phone:PhoneApplicationPage.Resources> 

...

还在里面MainPageView.xaml

<bab:BindableAppBar Grid.Row="2" Mode="Minimized"> 
    <bab:BindableAppBarButton micro:Message.Attach="[Event Click] = [Action ShowFilter($view, $eventArgs]"> 

    </bab:BindableAppBarButton> 
</bab:BindableAppBar> 

MainPageViewModel.cs

public void ShowFilter(object sender, RoutedEventArgs e) 
{ 
    var view= sender as MainPageView; 

    CustomMessageBox messageBox = new CustomMessageBox() 
    { 
     ContentTemplate = (DataTemplate)view.Resources["PivotContentTemplate"], 
     LeftButtonContent = "filter", 
     RightButtonContent = "cancel", 
     IsFullScreen = true // Pivots should always be full-screen. 
    }; 

    messageBox.Dismissed += (s1, e1) => 
    { 
     switch (e1.Result) 
     { 
      case CustomMessageBoxResult.LeftButton: 
       // Do something. 
       break; 
      case CustomMessageBoxResult.RightButton: 
       // Do something. 
       break; 
      case CustomMessageBoxResult.None: 
       // Do something. 
       break; 
      default: 
       break; 
     } 
    }; 

    messageBox.Show(); 
} 

public void OnCurrenciesChanged(SelectionChangedEventArgs e) 
{ 

} 

对于您的信息,我使用Caliburn.Micro和WP工具包的CustomMessageBoxListPicker

我收到异常No target found for method OnCurrenciesChanged。当我在列表选取器中选择几个项目并单击任何按钮以保存更改时,我只会收到异常。另一件事是OnCurrenciesChanged根本没有被触发。

我认为(根据我读到目前为止)每当调用CustomMessageBox时,其操作的datacontext不再指向MainPageViewModel因此它找不到方法。但我不确定如何实际做到这一点。

更多细节: 异常发生,我点击鼠标左键(复选标记) exception_here

更新 到目前为止,我有尝试以下后:

<StackPanel Margin="12,0,0,0" DataContext="{Binding DataContext, RelativeSource={RelativeSource TemplatedParent}}"> //also tried with Self 

,我也加入这个时我例化messageBox

 var messageBox = new CustomMessageBox() 
     { 
      ContentTemplate = (DataTemplate)view.Resources["PivotContentTemplate"], 
      DataContext = view.DataContext, // added this 
      LeftButtonContent = "filter", 
      RightButtonContent = "cancel", 
      IsFullScreen = true 
     }; 

这个想法是,当创建messsagebox时,datacontext将与视图实例化时相同。但是,似乎datacontext不会继承PickerList

好吧,所以我设法让这个工作。解决方案并不美观,我认为它首先击败了MVVM的目的。

基于http://wp.qmatteoq.com/first-steps-in-caliburn-micro-with-windows-phone-8-how-to-manage-different-datacontext/,模板内DataContext将不同。所以,我需要以某种方式告诉ListPicker使用正确的DataContext

以上链接提供的解决方案不适用于我。我认为这是因为当在CustomMessageBox内部调用ListPicker时,MainPageViewModel不再可用,或者它看起来不能像异常所建议的那样找到它。因此,根据问题中的上述代码示例,即使我将DataContext设置为CustomMessageBox,但它也不会被ListPicker以某种方式继承。

这里是我的解决方案:

 var messageBox = new CustomMessageBox() 
     { 
      Name = "FilterCustomMessageBox", // added this 
      ContentTemplate = (DataTemplate)view.Resources["PivotContentTemplate"], 
      DataContext = view.DataContext, 
      LeftButtonContent = "filter", 
      RightButtonContent = "cancel", 
      IsFullScreen = true 
     }; 

在XAML,我编辑这个

  <toolkit:ListPicker Header="currencies" SelectionMode="Multiple" 
           micro:Action.TargetWithoutContext="{Binding ElementName=FilterCustomMessageBox, Path=DataContext}" 
           micro:Message.Attach="[Event SelectionChanged] = [Action OnCurrenciesChanged($eventArgs)]"> 

这是丑陋的,因为这两个ViewModelView需要明确地知道Name。在WPF中,你可以在绑定中执行类似这样的操作来继承父/ etc的DataContext,但这不适用于WP。

{Binding DataContext, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGrid}}} 

如果有人有更好的解决方法,请让我知道!