C# WinUI3 Desktop:如何在 ListView 的选定项 DataTemplate 中引用或控制两个按钮?

C# WinUI3 Desktop: How can I reference or control two buttons in a ListView's selected item DataTemplate?

我在列表视图数据模板中有两个按钮。 'ButtonListViewEdit' 和 'ButtonListViewDelete'。 我希望这两个按钮保持 'collapsed' 直到选择列表视图项。只有所选列表视图项目上的按钮应该可见。

<Page.Resources>
    <DataTemplate x:Key="All_Staging_ListView_Template" x:DataType="local1:All_Staging_Data_Collection_ViewEdit">
        <Border BorderBrush="Aqua" BorderThickness="0 0 0 2" Padding="10,3" Margin="0,0,0,0">

            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition/>
                    <RowDefinition/>
                    <RowDefinition/>
                    <RowDefinition/>
                    <RowDefinition/>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="80"/>
                    <ColumnDefinition Width="190"/>
                    <ColumnDefinition MinWidth="90"/>
                    <ColumnDefinition Width="70"/>
                    <ColumnDefinition Width="20"/>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition/>
                    <ColumnDefinition/>
                </Grid.ColumnDefinitions>
                <TextBlock  Grid.Row="0" Grid.Column="0"                     Text="{x:Bind Metric_ID}"   x:Phase="1" FontWeight="ExtraBold" Margin="0,0,0,0"/>
                <TextBlock  Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="6" Text="{x:Bind Metric_Name}" x:Phase="1"                        Margin="0,0,20,0"/>
                <TextBlock  Grid.Row="0" Grid.Column="4"                     Text="{x:Bind ID}"          Visibility="Collapsed"             Margin="0,0,0,0"/>

                <TextBlock  Grid.Row="1" Grid.Column="0" Text="Period" FontWeight="Medium" FontSize="13" x:Name="MasterFontSize"/>
                <TextBlock  Grid.Row="1" Grid.Column="1" Text="{x:Bind Period}" FontSize="13"/>
                <TextBlock  Grid.Row="1" Grid.Column="2" Text="{Binding Path=Denominator_Ref}" FontWeight="Medium" FontSize="13"/>
                <TextBlock  Grid.Row="1" Grid.Column="3" Text="{Binding Path=Denominator}"     TextAlignment="Right" FontSize="13" />

                <TextBlock  Grid.Row="2" Grid.Column="0" Text="Product" FontWeight="Medium" FontSize="13"/>
                <TextBlock  Grid.Row="2" Grid.Column="1" Text="{x:Bind Product}" FontSize="13"/>
                <TextBlock  Grid.Row="2" Grid.Column="2" Text="{Binding Path=Numerator_Ref}"  FontWeight="Medium" FontSize="13"/>
                <TextBlock  Grid.Row="2" Grid.Column="3" Text="{Binding Path=Numerator}"      TextAlignment="Right" FontSize="13"/>
                <StackPanel Grid.Row="2" Grid.Column="6" Orientation="Horizontal" Margin="20,0,0,0">
                    <Button                          x:Name="ButtonListViewEdit"   Content="&#x270F;" Margin="0,0,0,0" Visibility="Collapsed" Click="ButtonListViewEdit_Click" Padding="1" FontSize="10"                  BorderBrush="Transparent" ToolTipService.ToolTip="Re-enter metric results"        Background="Transparent"/>
                    <Button                          x:Name="ButtonListViewDelete" Content="&#xE107;" Margin="0,0,0,0" Visibility="Visible" Click="ButtonListViewDelete_Click" Padding="1" FontFamily="Segoe MDL2 Assets" BorderBrush="Transparent" ToolTipService.ToolTip="Remove selected metric results" Background="Transparent"/>
                </StackPanel>

                <TextBlock  Grid.Row="3" Grid.Column="0" Text="Company" FontWeight="Medium" FontSize="13"/>
                <TextBlock  Grid.Row="3" Grid.Column="1" Text="{x:Bind Company}" FontSize="13"/>
                <TextBlock  Grid.Row="3" Grid.Column="2" Text="{Binding Path=Total_Ref}"  FontWeight="Medium" FontSize="13" />
                <TextBlock  Grid.Row="3" Grid.Column="3" Text="{Binding Path=Total}"      TextAlignment="Right" FontSize="13" />
                <TextBlock  Grid.Row="3" Grid.Column="6" Text="Entered by" FontWeight="Medium" FontSize="13" Margin="20,0,10,0"/>
                <TextBlock  Grid.Row="3" Grid.Column="7" Text="{x:Bind Insert_User_Name}" FontSize="13"/>

                <TextBlock  Grid.Row="4" Grid.Column="0" Text="State"          FontWeight="Medium" FontSize="13"/>
                <TextBlock  Grid.Row="4" Grid.Column="1" Text="{x:Bind State}"                     FontSize="13"/>
                <TextBlock  Grid.Row="4" Grid.Column="6" Text="Entered Date"   FontWeight="Medium" FontSize="13" Margin="20,0,10,0" />
                <TextBlock  Grid.Row="4" Grid.Column="7" Text="{x:Bind Insert_Date}"               FontSize="13"/>

            </Grid>
        </Border>
    </DataTemplate>
</Page.Resources>

贡献者 mm8 在我的 ListView DataTemplate 中只有一个按钮时帮助了我,mm8 向我展示了 'getting a reference to the Button using the VisualTreeHelper class in your event handler:'

的解决方案

我成功实现了mm8的解决方案。此处显示:

private void All_Staging_ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    All_Staging_Data_Collection_ViewEdit listitem = new All_Staging_Data_Collection_ViewEdit();
    listitem = (All_Staging_Data_Collection_ViewEdit)All_Staging_ListView.SelectedItem;
    Debug.WriteLine($"ListView >>>>>>>>>>>>>>>>>>>>>>>>>>>>> SelectionChanged > Metric ID: {listitem.Metric_ID}, ID: {listitem.ID}");

    foreach (object selectedItem in e.AddedItems)
        DisplayOrHideButton(selectedItem, true);
    foreach (object selectedItem in e.RemovedItems)
        DisplayOrHideButton(selectedItem, false);
}

private void DisplayOrHideButton(object item, bool display)
{
    ListViewItem container = All_Staging_ListView.ContainerFromItem(item) as ListViewItem;
    if (container != null)
    {
        Button button = FindVisualChild<Button>(container);
        if (button != null)
            button.Visibility = display ? Visibility.Visible : Visibility.Collapsed;
    }
}

private static T FindVisualChild<T>(DependencyObject obj) where T : DependencyObject
{
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
    {
        DependencyObject child = VisualTreeHelper.GetChild(obj, i);
        if (child != null && child is T t)
            return t;
        else
        {
            T childOfChild = FindVisualChild<T>(child);
            if (childOfChild != null)
                return childOfChild;
        }
    }
    return null;
}

应该如何修改此解决方案,以便当用户选择列表项时,我添加的新的第二个按钮也可以显示?

谢谢 mm8 和 Whosebug。 此致

以下代码应该找到模板中的所有按钮,并在选择或取消选择项目时显示或隐藏它们:

private void DisplayOrHideButton(object item, bool display)
{
    ListViewItem container = All_Staging_ListView.ContainerFromItem(item) as ListViewItem;
    if (container != null)
    {
        IEnumerable<Button> buttons = FindVisualChildren<Button>(container);
        if (buttons != null)
            foreach (Button button in buttons)
                button.Visibility = display ? Visibility.Visible : Visibility.Collapsed;
    }
}

private static IEnumerable<T> FindVisualChildren<T>(DependencyObject obj) where T : DependencyObject
{
    if (obj == null)
        yield return (T)Enumerable.Empty<T>();

    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
    {
        DependencyObject child = VisualTreeHelper.GetChild(obj, i);
        if (child == null)
            continue;
        if (child is T t)
            yield return t;

        foreach (T childOfChild in FindVisualChildren<T>(child))
            yield return childOfChild;
    }
}