[英]Using WPF, how can I programmatically disable buttons that were created in XAML for a Listview control?
I created a WPF Listview and is populated with instances of ProductCategory.我创建了一个 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; }
}
Next I create the list, populate it and assign it to the Listview control.接下来我创建列表,填充它并将其分配给 Listview 控件。
private List myProductList = new List();私有列表 myProductList = new List();
// add some items to myProductList // 添加一些项目到 myProductList
// assign product list to ItemsSource property of a ListView // 将产品列表分配给 ListView 的 ItemsSource 属性
myListView.ItemsSource = myProductList; myListView.ItemsSource = myProductList;
In the XAML code, a button labelled "Edit" is added to each row.在 XAML 代码中,每行都添加了一个标有“编辑”的按钮。 Each row represents an instance of ProductCategory:
每行代表 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>
When the user clicks the button, a dialog appears and the user can edit the data for an instance of ProductCategory.当用户单击该按钮时,将出现一个对话框,用户可以编辑 ProductCategory 实例的数据。 When the user closes the dialog, the user is returned to the Listview.
当用户关闭对话框时,用户将返回到列表视图。
At this point I want to disable all the buttons in the Listview.此时我想禁用 Listview 中的所有按钮。 How could I programmatically achieve this goal?
我怎样才能以编程方式实现这个目标?
The buttons are not accessible in myListView.ItemsSource.这些按钮在 myListView.ItemsSource 中不可访问。
I created a List to stores the results.我创建了一个列表来存储结果。 You can see that I pick a couple of random buttons from the list and disable them.
您可以看到我从列表中随机选择了几个按钮并将其禁用。 The Button_Click is from a button that I added so I could have somewhere to start.
Button_Click 来自我添加的按钮,因此我可以从某个地方开始。 Executing the code from within the constructor after IntializeComponent() should give you a list of all your buttons
在 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;
}
From the suggested solutions, here is the code to solve my problem:从建议的解决方案中,这里是解决我的问题的代码:
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;
}
});
}
This is very easy to do using MVVM.使用 MVVM 很容易做到这一点。
I'm showing a simple example - it breaks MVVM somewhat, but will give you an idea of how it should work.我展示了一个简单的例子——它在某种程度上打破了 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 and RelayCommand classes . BaseInpc 和 RelayCommand 类。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.