0

我对 XAML 和 Caliburn.Micro 有点陌生。我遇到了一个“奇怪”的问题。

我正在使用 Caliburn.Micro 制作一个 Windows Phone 8 应用程序,并且我有一个带有项目的 ListBox,然后它包括另一个带有一些细节行的内部 ListBox。

        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,5,12,5" >
        <ListBox x:Name="CurrentStunts"
                 cal:Message.Attach="[Tap]=[Action OpenStuntOnWeb(CurrentStunts.SelectedItem)]">
            <ListBox.ItemTemplate>
                <DataTemplate>
                        <Grid DataContext="{Binding}" Background="#FFCC00" Margin="0,10,0,10">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="45"/>
                            <ColumnDefinition Width="*" MinWidth="345"/>
                            <ColumnDefinition Width="40"/>
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="*"/>
                        </Grid.RowDefinitions>
                        <StackPanel Grid.Column="0">
                             <StackPanel.Background>
                                <ImageBrush ImageSource="{Binding StuntDetails.Channel,Converter={StaticResource ChannelIconConverter}}"  Stretch="Uniform" AlignmentY="Top"/>
                             </StackPanel.Background>
                        </StackPanel>
                        <StackPanel Grid.Column="1" Orientation="Vertical">
                            <TextBlock Text="{Binding Title}" Foreground="#CC0000" TextWrapping="Wrap"/>
                            <TextBlock Text="{Binding SubTitle}" Foreground="#336699" TextWrapping="Wrap"/>
                            <ListBox ItemsSource="{Binding DetailLines}">
                                <ListBox.ItemTemplate>
                                    <DataTemplate>
                                        <TextBlock Text="{Binding}" Foreground="#336699" FontSize="14" TextWrapping="Wrap"/>
                                    </DataTemplate>
                                </ListBox.ItemTemplate>
                            </ListBox>

                        </StackPanel>
                        <StackPanel Grid.Column="2" Orientation="Vertical">
                            <TextBlock Text="{Binding StuntDetails.NewPrice}" Foreground="#CC0000" />
                                <Grid HorizontalAlignment="Left" VerticalAlignment="Top">
                                    <Grid.RowDefinitions>
                                        <RowDefinition Height="1*"/>
                                        <RowDefinition Height="1*"/>
                                    </Grid.RowDefinitions>
                                    <TextBlock HorizontalAlignment="Left" Text="{Binding StuntDetails.OldPrice}" VerticalAlignment="Top" Grid.RowSpan="2" Foreground="#336699"/>
                                    <Border BorderThickness="0,0,0,1" BorderBrush="#336699" >
                                    </Border>
                                </Grid>
                        </StackPanel>
                    </Grid>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>

带有 cal:Message.Attach="[Tap]=[Action OpenStuntOnWeb(CurrentStunts.SelectedItem)]" 的视图模型中的代码如下:

        public void OpenStuntOnWeb(StuntSummary currentItem)
    {
        if (currentItem != null)
        {
            var uri = stuntManager.BuildStuntLink(currentItem.StuntDetails);

            var webBrowserTask = new WebBrowserTask();
            webBrowserTask.Uri = uri;
            webBrowserTask.Show();
        }
    }

问题是当启动应用程序并单击内部列表框 (DetailLines) 上的任意位置时,方法 public void OpenStuntOnWeb(StuntSummary currentItem) 中的参数“currentItem”为空。当单击外部 ListBox CurrentStunts(例如在 Title 或 SubTitle 上)时,它可以正常工作并填写参数。

更奇怪的是,当您单击外部 ListBox,然后单击内部 ListBox 时,它也可以正常工作并填写参数。只有第一次单击内部 ListBox 时,“currentItem”才为空。

我坚持这一点,所以任何帮助将不胜感激。

4

1 回答 1

0

这里的问题是您正在响应Tap事件。点击事件很可能在SelectedItem设置后广播,但由于您正在点击内部控件,因此您没有从外部列表框中选择任何项目 - 您仍然得到Tap但不是 a SelectedItem(您可能想尝试SelectionChanged)。

当点击内部列表框时,外部列表框正在响应Tap事件,但由于您没有点击外部列表框,因此未设置选择,因此将空值传递给该方法。

编辑:

好的,使用 CMSpecialValues和我在此处发布的代码:RadMenu 和 RadMenuItem Caliburn.Micro

您可以提取DataContext最初调用事件的项目(ListBoxItem启动事件并将其冒泡到ListBox触发它的Tap事件,因此OriginalSource路由事件将是有ListBoxItem 希望的- 无论哪种方式项目都应该有权利DataContext!)

然后你可以使用

cal:Message.Attach="[Event Tap] = [Action DoSomething($originalsourcedatacontext)]"

所以总结一下:

将此添加到 CM 引导程序(Configure方法通常是最佳位置)

MessageBinder.SpecialValues.Add("$originalsourcedatacontext", (context) =>
{
    if (context.EventArgs is EventArgs)
    {          
        var e = context.EventArgs as EventArgs;

        // If the control is a FrameworkElement it will have a DataContext which contains the bound item
        var fe = e.OriginalSource as FrameworkElement;

        if (fe != null)
            return fe.DataContext;
    }

    return null;
});
于 2013-05-03T13:15:47.467 回答