I created a WPF Listview and is populated with instances of 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.
private List myProductList = new List();
// add some items to myProductList
// assign product list to ItemsSource property of a ListView
myListView.ItemsSource = myProductList;
In the XAML code, a button labelled "Edit" is added to each row. Each row represents an instance of 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. 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. How could I programmatically achieve this goal?
The buttons are not accessible in myListView.ItemsSource.
CodePudding user response:
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. Executing the code from within the constructor after IntializeComponent() should give you a list of all your buttons
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;
}
CodePudding user response:
This is very easy to do using MVVM.
I'm showing a simple example - it breaks MVVM somewhat, but will give you an idea of how it should work.
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>