【问题标题】:when clicking on inner list in xaml, parameter to tap event is null单击 xaml 中的内部列表时,点击事件的参数为空
【发布时间】:2013-05-03 12:52:37
【问题描述】:

我对 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();
        }
    }

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

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

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

【问题讨论】:

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


    【解决方案1】:

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

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

    编辑:

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

    您可以提取最初调用事件的项目的DataContextListBoxItem 启动事件并将其冒泡到触发它的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;
    });
    

    【讨论】:

    • 您好,感谢您的回复。我试了一下,但没有运气。它现在只会在单击外部 ListBox 时打开。以前,一旦单击外部 ListBox,我就可以按回并按下内部 ListBox 中的另一个项目,它会起作用。此外,SelectionChanged 带来了另一个问题:当人们点击它时,他们按下并再次点击它,事件在逻辑上不会触发。
    • 您能否发布一些布局截图并详细说明预期的行为?我正在尝试弄清楚您真正想要它做什么,并且由于您绑定到ItemsSource,每个项目都已包含在子控件的DataContext 中,所以也许您可以将Tap 事件降低向下,还是获取被点击项目的数据上下文?可能可以使用 CM SpecialValues 来获取被点击项目的数据上下文 - 我之前用一个例子回答了另一个问题,让我看看我能不能找到它
    • 找到它 - 信息在这里:stackoverflow.com/questions/15913380/… - 如果你要使用它并从操作的发送者那里获取DataContext,你可以提取绑定的项目,这将自动传递给方法 - 我会稍微编辑一下答案
    • 嘿查理。非常感谢你的帮助 !与此同时,我意识到我是个白痴:) 我有一个纯文本项目的子列表,我还有一个专门用来保存我的视图对象的对象。所以我没有只是将所有文本串在我的视图对象的 1 个“详细信息”属性中,然后用文本块显示它。不过,我会将您的回复标记为答案,这可能会帮助有更好理由拥有子列表的人:) 再次感谢!
    猜你喜欢
    • 1970-01-01
    • 2020-03-23
    • 1970-01-01
    • 1970-01-01
    • 2017-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多