【问题标题】:Getting ListBoxItem from item template control event从项模板控件事件中获取 ListBoxItem
【发布时间】:2011-08-10 21:29:43
【问题描述】:

在下面的 WPF XAML 代码中,如果我在模板化 Button 的 SelectTaskItemClick 事件中,如何获取当前选择的 ListBoxItem ItemSource 对象?

    <!-- ListBox ITEMS -->
    <TaskDash:ListBoxWithAddRemove x:Name="listBoxItems" Grid.Row="1" Grid.Column="3" Grid.RowSpan="3"
        ItemsSource="{Binding}">
        <!--ItemsSource="{Binding}" DisplayMemberPath="Description">-->
        <Style TargetType="ListBoxItem">
            <Setter Property="IsSelected" Value="{Binding Path=Selected}"/>
        </Style>
        <TaskDash:ListBoxWithAddRemove.ItemTemplate>
            <DataTemplate>
                <DockPanel>
                    <Button DockPanel.Dock="Left" Click="SelectTaskItemClick">SELECT</Button>
                    <TextBox DockPanel.Dock="Left" Name="EditableDescription" Text="{Binding Description}" Height="25" Width="100" />
                    <Button DockPanel.Dock="Left" Click="EditTaskItemClick">EDIT</Button>
                </DockPanel>
            </DataTemplate>
        </TaskDash:ListBoxWithAddRemove.ItemTemplate>
    </TaskDash:ListBoxWithAddRemove>

如果我尝试获取 Parent 或 TemplateParent,它会给我 ContentPresenter 或 Style 或类似的东西。

    private void SelectTaskItemClick(object sender, RoutedEventArgs e)
    {
        Button taskItemButton = (Button) e.OriginalSource;
        ContentPresenter taskItem = (ContentPresenter) taskItemButton.TemplatedParent;
        taskItem = (ContentPresenter)taskItemButton.TemplatedParent;
        Style taskItem2 = taskItem.TemplatedParent;
        taskItem2 = taskItem.TemplatedParent;
        DependencyObject taskItem3 = taskItem2.Parent;
        //DependencyObject taskItem3 = taskItem2.TemplatedParent;
        //TaskItem taskItemObj = taskItem2;
    }

在上面的代码中,我猜它是从定义了自定义 ListBoxWithAddRemove 控件的 App.XAML 中获取的。我该如何遍历实际表单的 XAML [上面显示的第一个代码]?

<Style x:Key="{x:Type TaskDash:ListBoxWithAddRemove}" TargetType="{x:Type     TaskDash:ListBoxWithAddRemove}">
            <Setter Property="Margin" Value="3" />
            <Setter Property="SnapsToDevicePixels" Value="True"/>
            <Setter Property="OverridesDefaultStyle" Value="True"/>
            <Setter Property="KeyboardNavigation.TabNavigation" Value="None"/>
            <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
            <Setter Property="MinWidth" Value="120"/>
            <Setter Property="MinHeight" Value="20"/>
            <Setter Property="AllowDrop" Value="true"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type TaskDash:ListBoxWithAddRemove}">
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="25" />
                                <RowDefinition Height="*" />
                            </Grid.RowDefinitions>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="*" />
                                <ColumnDefinition Width="*" />
                            </Grid.ColumnDefinitions>

                            <Button Grid.Column="0" Grid.Row="0" 
                                    Click="DeleteControlClick">Delete</Button>
                            <Button Grid.Column="1" Grid.Row="0" 
                                    Click="AddControlClick">Add</Button>
                            <Border 
                                Grid.Column="0" Grid.Row="1" Grid.ColumnSpan="2"
                                  Name="Border" 
                                  Background="{StaticResource WindowBackgroundBrush}"
                                  BorderBrush="{StaticResource SolidBorderBrush}"
                                  BorderThickness="1"
                                  CornerRadius="2">
                                <ScrollViewer 
                                    Margin="0"
                                    Focusable="false">
                                    <StackPanel Margin="0" IsItemsHost="True" />
                                </ScrollViewer>
                            </Border>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

【问题讨论】:

    标签: c# wpf xaml styles


    【解决方案1】:

    如果您有正确类型的对象,您可以使用VisualTreeHelper 向上走并停下来,例如

    private void SelectTaskItemClick(object sender, RoutedEventArgs e)
    {
        var b = sender as Button;
        DependencyObject item = b;
        while (item is ListBoxItem == false)
        {
            item = VisualTreeHelper.GetParent(item);
        }
        var lbi = (ListBoxItem)item;
        //...
    }
    

    如果您只想选择可以(并且应该)通过已建立的绑定完成的项目,例如

    private void SelectTaskItemClick(object sender, RoutedEventArgs e)
    {
        // The DataContext should be an item of your class that should
        // have a Selected property as you bind to it in a style.
        var data = (sender as FrameworkElement).DataContext as MyClass;
        data.Selected = true;
    }
    

    【讨论】:

    • 谢谢,这主要是我需要的。看起来我还需要做的是删除 Style 元素。我不断得到一个 ListBoxItem,其 DataContext 为 STYLE 而不是 TASKITEM:
    • @Shawn: 样式本身很好,但你不应该像以前那样将它添加到 ListBox 中,而是将其设置为 ItemContainerStyle: &lt;TaskDash:ListBoxWithAddRemove.ItemContainerStyle&gt;&lt;!-- Style here --&gt;&lt;/TaskDash:ListBoxWithAddRemove.ItemContainerStyle&gt;
    【解决方案2】:

    假设

    <Style TargetType="ListBoxItem">
        <Setter Property="IsSelected" Value="{Binding Path=Selected}"/>
    </Style>
    

    按照您想要的方式工作,您应该能够遍历 DataContext 中用作列表框的 ItemsSource 的项目,并检查每个项目的 Selected 属性以找到当前选择的项目。从 ListBox 中确定所选项目的更典型方法是使用 listBox.SelectedItem,其中 listBox 是一个引用相关 ListBox 的变量。或者,您可以通过 sender 参数访问它到 SelectTaskItemClick 方法。您可以尝试的另一种方法是遍历可视化树的辅助方法,例如 The Coding BlokeThe Code Project - LINQ to Visual Tree 中所述。

    【讨论】:

    • 我觉得按钮的重点是选择被点击的项目,所以没有预先选择。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-12
    • 1970-01-01
    • 1970-01-01
    • 2019-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多