【问题标题】:Get ListBox DataContext from UserControl从 UserControl 获取 ListBox DataContext
【发布时间】:2023-03-31 03:00:02
【问题描述】:

我有一个用户控件,里面有一个按钮。 UserControl 它的 DataContext 是我的模型之一,因此我可以绑定到它。但是,对于按钮,我希望能够从我的视图模型中调用一个方法。 ListBox 的 DataContext 就是这个 ViewModel。

因为我的 ContextMenu 也需要相同的 DataContext,所以我将它们绑定如下:

Command="{Binding Path=DataContext.AttendEventCommand, ElementName=EventListBox}"

调用 EventListBox 元素并使用其 DataContext 调用 AttendEventCommand。但是,我想从 UserControl 上的按钮调用 AttendEventCommand。我试过用同样的方法做,但遗憾的是它不起作用。

我的数据上下文是这样设置的:

DataContext="{Binding Path=EventList, Source={StaticResource Locator}}

我的列表框代码:

<ListBox x:Name="EventListBox" ItemsSource="{Binding Occurrences}" Margin="0,50,0,0" >
    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <Grid>
                                <uctl:EventListItem HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Width="auto" Height="auto">
                                    <toolkit:ContextMenuService.ContextMenu>
                                        <toolkit:ContextMenu IsZoomEnabled="True" x:Name="ContextMenu">
                                            <toolkit:MenuItem x:Name="Going" Header="{Binding AttendingText}" Command="{Binding Path=DataContext.AttendEventCommand, ElementName=EventListBox}" CommandParameter="{Binding}"/>
                                        </toolkit:ContextMenu>
                                    </toolkit:ContextMenuService.ContextMenu>
                                </uctl:EventListItem>
                            </Grid>
                        </DataTemplate>
                    </ListBox.ItemTemplate>
</ListBox>

还有我的 UserControl 按钮:

<Button Grid.RowSpan="3" Grid.Column="5" Opacity="0" Command="{Binding Path=DataContext.AttendEventCommand, ElementName=EventListBox}" CommandParameter="{Binding}"/>

【问题讨论】:

  • 我在您的代码中没有看到您实际设置了 ListBox 的 DataContext。 ItemsSource != DataContext,因此您对命令的绑定永远不会起作用。
  • 我省略了那部分代码,因为对我来说很明显我会首先设置 DataContext。我已将设置数据上下文的代码行添加到示例中以进行说明。

标签: xaml windows-phone-8


【解决方案1】:

我相信您的问题不在于您想做的事情不起作用;相反,您的设计似乎是错误的。

你现在拥有的是这样的: 你有一个Window,它有一个DataContext 和一个ListBox。 ListBox 有一个ItemsSource,我们假设它是一些IEnumerable&lt;Occurrence&gt;。

ListBox 中每个项目的外观是一个EventListItem,它是一个至少包含一个Button 的UserControl。

您希望 Button 的 Command 调用您的 Window 的 DataContext 上的方法。

最后一句话是错误的。项目具有按钮的事实意味着它执行与项目相关的操作,而不是窗口内容。如果这不是真的,那么可能应该重新考虑窗口和列表框项的视觉设计。

如果按钮实际上影响了项目,那么您不应该调用 Window 的 DataContext 上的方法,而是调用项目的 DataContext 上的方法。

解决方案是将模型对象Occurrence 包装在它自己的视图模型类中。我们称之为OccurrenceViewModel。您的ListBox 的ItemsSource 将是IEnumerable&lt;OccurrenceViewModel&gt; 的某种形式。因为它是一个视图模型,所以它可以实现Command 方法,然后可以以一种或另一种方式操纵Occurrence,直接或最好将其传递给实现用例的某个类。

【讨论】:

    【解决方案2】:

    您的EventListItem 的DataContext 将是您的ItemsSource 的模型,因为它是DataTemplate 的一部分。所以你必须明确地设置它。

    请参阅How to implement a navigation button 了解我将用作解决方案的一些代码。


    让我们假设您的自定义 UserControl 非常基本,如下所示:

    <UserControl>
        <Grid x:Name="LayoutRoot" Background="{StaticResource PhoneChromeBrush}">
            <Button Command="{Binding DataContext.SimpleCommand}" CommandParameter="1"></Button>
        </Grid>
    </UserControl>
    

    其中 SimpleCommand 是您要在顶视图模型中调用的命令。

    那么你必须把你的DataTemplate改成

    <DataTemplate>
        <Grid>
            <uctl:EventListItem
                DataContext="{Binding ElementName=myListBox}"/>
            <!-- more xaml -->
        </Grid>
    </DataTemplate>
    

    您的&lt;toolkit:ContextMenu&gt; 应该可以正常工作。


    在ICommand的Execute函数处设置一个断点,你会看到它会得到 每次都去那里。

    public void Execute(object parameter)
    {
       // logic to execute when user hits the command
       int debug_var = 0;   // put a break point here
    }
    

    【讨论】:

    • 我在 UserControl 中有其他项需要绑定到 ItemSource,通过更改整个 UserControl 的 DataContext 这会中断。不过还是谢谢你的回答。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-27
    相关资源
    最近更新 更多