0

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

这是我的代码:

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 ToolkitCustomMessageBoxListPicker.

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

我认为(基于我目前阅读的内容)每当CustomMessageBox调用 get 时,其操作的数据上下文不再指向,MainPageViewModel因此它无法找到该方法。但我不确定如何实际做到这一点。

更多详细信息:单击左侧按钮后发生异常(复选标记) 异常_这里

更新 到目前为止,我尝试了以下方法:

<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
        }; 

这个想法是,当创建消息框时,数据上下文将与实例化视图时相同。但是,似乎数据上下文没有被PickerList

4

1 回答 1

2

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

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

上面链接提供的解决方案对我不起作用。我认为这是因为 when ListPickeris called inside CustomMessageBox,MainPageViewModel不再可用或者似乎无法按照异常的建议找到它。因此,根据问题中的上述代码示例,即使我将正确设置DataContextCustomMessageBox,它也不会以某种方式被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)]">

这很难看,因为两者都ViewModel需要View明确知道Name. 在 WPF 中,您可以在绑定中执行类似的操作以继承父级/etc 的 DataContext,但这不适用于 WP。

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

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

于 2013-08-05T15:16:58.123 回答