我想创建某种过滤器,当用户点击应用栏中的过滤器按钮时,它会启动一个带有列表选择器的弹出页面。我用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)
{
}
为了您的信息,我正在为CustomMessageBox
和ListPicker
使用Caliburn.Micro和WP Toolkit。
我收到例外No target found for method OnCurrenciesChanged
。当我在列表选择器中选择几个项目并单击任何按钮以保存更改时,我只收到异常。另一件事是OnCurrenciesChanged
根本没有被触发。
我认为(基于我到目前为止所读到的)每当调用CustomMessageBox
时,其操作的datacontext不再指向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
};
这个想法是,当创建messsagebox时,datacontext将与实例化视图时相同。但是,似乎datacontext不会被PickerList
答案 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)]">
这很难看,因为ViewModel
和View
都需要明确知道Name
。在WPF中,您可以在绑定中执行类似的操作以继承父/ etc的DataContext,但这不适用于WP。
{Binding DataContext, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGrid}}}
如果有人有更好的解决方法,请告诉我!