簡體   English   中英

使用 WPF,如何以編程方式禁用在 XAML 中為 Listview 控件創建的按鈕?

[英]Using WPF, how can I programmatically disable buttons that were created in XAML for a Listview control?

我創建了一個 WPF 列表視圖,並填充了 ProductCategory 的實例。

public class ProductCategory
{
    public int Id { get; set; }

    public string CategoryName { get; set; }

    public DateTime CreatedDate { get; set; }

    public DateTime LastUpdated { get; set; }
}

接下來我創建列表,填充它並將其分配給 Listview 控件。

私有列表 myProductList = new List();

// 添加一些項目到 myProductList

// 將產品列表分配給 ListView 的 ItemsSource 屬性

myListView.ItemsSource = myProductList;

在 XAML 代碼中,每行都添加了一個標有“編輯”的按鈕。 每行代表 ProductCategory 的一個實例:

    <ListView x:Name="myListView" Height="352" HorizontalAlignment="Left" Margin="20,90,0,0" VerticalAlignment="Top" Width="1008">
        <ListView.View>
            <GridView>
                <GridViewColumn Header="Category Name" DisplayMemberBinding="{Binding CategoryName}" Width="200"/>
                <GridViewColumn Header="Created Date" DisplayMemberBinding="{Binding CreatedDate}" Width="200"/>
                <GridViewColumn Header="Last Updated" DisplayMemberBinding="{Binding LastUpdated}" Width="200"/>
                <GridViewColumn Header="Edit" Width="200">
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <Button Content="Edit" Click="EditCategory" CommandParameter="{Binding}"/>
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>
            </GridView>
        </ListView.View>
    </ListView>

當用戶單擊該按鈕時,將出現一個對話框,用戶可以編輯 ProductCategory 實例的數據。 當用戶關閉對話框時,用戶將返回到列表視圖。

此時我想禁用 Listview 中的所有按鈕。 我怎樣才能以編程方式實現這個目標?

這些按鈕在 myListView.ItemsSource 中不可訪問。

我創建了一個列表來存儲結果。 您可以看到我從列表中隨機選擇了幾個按鈕並將其禁用。 Button_Click 來自我添加的按鈕,因此我可以從某個地方開始。 在 IntializeComponent() 之后從構造函數中執行代碼應該會為您提供所有按鈕的列表

List<Button> buttons = 
    new List<Button>();

private void Button_Click(object sender, RoutedEventArgs e)
{
    myListView.Items
        .Cast<dynamic>()
        .ToList()
        .ForEach(item => {
            var listviewitem = 
               (ListViewItem)             
                   (myListView
                       .ItemContainerGenerator
                           .ContainerFromItem(item));

            Button editbutton = 
                FindVisualChild<Button>
                    (listviewitem);

            buttons
                .Add(editbutton);
        });

    buttons[1]
        .IsEnabled = false;
    buttons[3]
        .IsEnabled = false;
}

private childItem FindVisualChild<childItem>(DependencyObject obj)
    where childItem : DependencyObject
{
    for (int i = 0; 
             i < VisualTreeHelper
                     .GetChildrenCount(obj); 
                         i++)
    {
        DependencyObject child = 
            VisualTreeHelper
                .GetChild(obj, i);

        if (child != null 
               && child is childItem)
        {
            return 
                (childItem)child;
        }
        else
        {
            childItem childOfChild = 
                FindVisualChild<childItem>
                    (child);

            if (childOfChild != null)
                return 
                    childOfChild;
        }
    }
    return null;
}

從建議的解決方案中,這里是解決我的問題的代碼:

    private childItem FindVisualChild<childItem>(DependencyObject obj) where childItem : DependencyObject
    {
        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
        {
            DependencyObject child = VisualTreeHelper.GetChild(obj, i);

            if (child != null && child is childItem)
            {
                return (childItem)child;
            }
            else
            {
                childItem childOfChild = FindVisualChild<childItem>(child);

                if (childOfChild != null)
                {
                    return childOfChild;
                }
            }
        }
        return null;
    }

    private void disableEditButtonsInListView()
    {
        myListView.Items.Cast<dynamic>().ToList().ForEach(item =>
        {
            var myListViewItem = (ListViewItem)(myListView.ItemContainerGenerator.ContainerFromItem(item));
            Button editButton = FindVisualChild<Button>(myListViewItem);
            if (editButton != null)
            {
                editButton.IsEnabled = false;
            }
        });
    }

使用 MVVM 很容易做到這一點。
我展示了一個簡單的例子——它在某種程度上打破了 MVVM,但會讓你了解它應該如何工作。

using Simplified;
using System;
using System.Collections.ObjectModel;
using System.Windows;

namespace Core2022.SO.user2949159
{
    public class ProductsViewModel : BaseInpc
    {
        public ObservableCollection<ProductCategory> Products { get; } = new()
        {
            new ProductCategory() {Id = 1, CategoryName = "Electronics", CreatedDate = DateTime.Now.AddDays(-15).Date, LastUpdated= DateTime.Now.AddDays(-5).Date},
            new ProductCategory() {Id = 2, CategoryName = "Сlothes", CreatedDate = DateTime.Now.AddDays(-7).Date, LastUpdated= DateTime.Now.AddDays(-1).Date}
        };

        private RelayCommand? _editCommand;
        private bool _editingOff;

        public RelayCommand EditCommand => _editCommand ??= new RelayCommand<ProductCategory>(EditExecute, EditCanExecute);

        public bool EditingOff
        {
            get => _editingOff;
            set
            {
                if (Set(ref _editingOff, value))
                    EditCommand.RaiseCanExecuteChanged();
            }
        }
        private bool EditCanExecute(ProductCategory product) => !EditingOff;

        private void EditExecute(ProductCategory product)
        {
            // Some Code for edit product
            MessageBox.Show($"{product.Id}: {product.CategoryName}");
        }
    }
<Window x:Class="Core2022.SO.user2949159.ProductsWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Core2022.SO.user2949159"
        mc:Ignorable="d"
        Title="ProductsWindow" Height="450" Width="800"
        DataContext="{DynamicResource vm}">
    <Window.Resources>
        <local:ProductsViewModel x:Key="vm"/>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <CheckBox Content="Editing Off" IsChecked="{Binding EditingOff}" Margin="5"/>
        <ListView Grid.Row="1" ItemsSource="{Binding Products}" HorizontalAlignment="Left" Margin="20">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="Category Name" DisplayMemberBinding="{Binding CategoryName}" Width="200"/>
                    <GridViewColumn Header="Created Date" DisplayMemberBinding="{Binding CreatedDate}" Width="200"/>
                    <GridViewColumn Header="Last Updated" DisplayMemberBinding="{Binding LastUpdated}" Width="200"/>
                    <GridViewColumn Header="Edit" Width="200">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <Button Content="Edit"
                                        CommandParameter="{Binding}"
                                        Command="{Binding EditCommand, Mode=OneWay, Source={StaticResource vm}}"/>
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                </GridView>
            </ListView.View>
        </ListView>
    </Grid>
</Window>

BaseInpc 和 RelayCommand 類

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM