CaliburnMicro Action不会在数据模板内部触发

时间:2013-08-04 15:20:14

标签: c# xaml windows-phone-8 caliburn.micro silverlight-toolkit

我想创建某种过滤器,当用户点击应用栏中的过滤器按钮时,它会启动一个带有列表选择器的弹出页面。我用Google搜索并尝试了很多解决方案,但仍无法使其正常工作。

以下是我的代码:

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)
{

}

为了您的信息,我正在为CustomMessageBoxListPicker使用Caliburn.Micro和WP Toolkit。

我收到例外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

继承

1 个答案:

答案 0 :(得分:2)

好的,所以我设法让这个工作。解决方案并不漂亮,我认为它首先胜过了MVVM的目的。

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

上面链接提供的解决方案对我不起作用。我认为这是因为在ListPicker内调用CustomMessageBox时,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}}}

如果有人有更好的解决方法,请告诉我!