Hi,
You can check this article with example code.
https://www.c-sharpcorner.com/UploadFile/33b051/delete-multiple-record-from-a-datagridview-using-checkbox-i/
This browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
Hi guys, I am new to WPF development. I'm trying to develop a program containing a Listbox and a Datagrid along with a Combobox and a Textbox. I'd like to establish a relationship among them but I face an issue.
First I illustrate with an screenshot:
The data in the Datagrid is independent to other controller, meaning no matter what operations I do on other controllers, the data in Datagrid remain unchanged. Even I change it manually in the GUI, the modification only works for current runtime. All data loads from an Excel file.
Expected is, user selects an item in the Listbox, then user can select in the Combobox, give value to Textbox and select some rows in the Datagrid by checking the checkboxes in the first column. After several such operations for each item in the Listbox, user can see the operation result of each item by selecting random item in the Listbox. For example, after mentioned operations, I select the first item, I can see values in Combobox, Textbox, especially the checked rows in Datagrid (All data remain displayed but some with checkbox checked).
Now I have finished the binding between item in Listbox and Combox and the relationship between item in Listbox and Textbox. The expected binding between Listbox and Datagrid still bothers me. I follow the MVVM to develop.
All useful code are below:
<Window x:Class="A350F_Change_Request.MainWindow"
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:A350F_Change_Request" xmlns:changeRequestVM="clr-namespace:A350F_Change_Request.ViewModels"
mc:Ignorable="d"
Title="MainWindow" Height="648" Width="1104.25" MinWidth="1148" MinHeight="648" ResizeMode="NoResize" WindowStartupLocation="CenterScreen">
<Window.DataContext>
<changeRequestVM:ChangeRequestViewModel/>
</Window.DataContext>
<Window.Resources>
<Style TargetType="{x:Type TabControl}">
<Setter Property="TabStripPlacement" Value="Top" />
<Setter Property="Margin" Value="0" />
<Setter Property="Padding" Value="0"/>
</Style>
<Style TargetType="TabItem">
<Setter Property="FontSize" Value="10"/>
<Setter Property="BorderBrush" Value="Pink"/>
<Setter Property="BorderThickness" Value="10"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Border x:Name="tabItemBorder" Background="{TemplateBinding Background}" BorderThickness="1,1,1,0"
BorderBrush="Black" Margin="0,0,0,0" CornerRadius="2,2,0,0" Padding="50,0,50,0">
<ContentPresenter ContentSource="Header" Margin="5" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="#fff291"/>
<Setter Property="Foreground" Value="#000"/>
</Trigger>
<Trigger Property="IsSelected" Value="false">
<Setter Property="Background" Value="#013268"/>
<Setter Property="Foreground" Value="#fff"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="ListBoxItem" x:Key="ContainerStyle">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True" >
<Setter Property="Background" Value="#fff291"/>
<Setter Property="Foreground" Value="#000"/>
</Trigger>
<Trigger Property="IsSelected" Value="False" >
<Setter Property="Foreground" Value="White"/>
<Setter Property="Background" Value="#013268"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid x:Name="mainGrid" Background="#FF111F74" HorizontalAlignment="Left" Height="619" VerticalAlignment="Top" Width="1142">
<Grid.RowDefinitions>
<RowDefinition Height="3*"/>
<RowDefinition Height="4*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="3*"/>
</Grid.ColumnDefinitions>
<Border Grid.Column="0" Grid.RowSpan="2" Background="#FF111F74"/>
<Border Grid.Column="1" Background="#FF111F74"/>
<Border Grid.Column="1" Grid.Row="1" Background="#FF111F74"/>
<ListBox x:Name="catDocListView" Grid.Column="0" Grid.RowSpan="2" Margin="16" ItemContainerStyle="{StaticResource ContainerStyle}" ItemsSource="{Binding viewModelSource}" DisplayMemberPath="displayName"/>
<StackPanel Grid.Column="1" Margin="16" Background="white" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Label Grid.Column="0" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="16">Material:</Label>
<ComboBox x:Name="materialCombo" Grid.Column="1" HorizontalAlignment="Stretch" Margin="8" ItemsSource="{Binding Path=materialSource}" Text="{Binding ElementName=catDocListView, Path=SelectedItem.Material}"/>
<Label Grid.Row="2" Grid.Column="0" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="16">ECN:</Label>
</Grid>
<TextBox Margin="8" Height="80" TextWrapping="Wrap" AcceptsReturn="True" Text="{Binding ElementName=catDocListView, Path=SelectedItem.ECN, Mode=TwoWay}"/>
<Button x:Name="export" Width="80" Height="20" Content="Export" HorizontalAlignment="Right" Margin="0,0,16,0" Click="export_Click"></Button>
</StackPanel>
<TabControl Grid.Row="1" Grid.Column="1" Margin="16">
<TabItem Header="General Notes" FontSize="16">
<DataGrid x:Name="generalNoteDG" CanUserAddRows="False" AutoGenerateColumns="False" ItemsSource="{Binding generalNoteSource}">
<DataGrid.Columns>
<DataGridCheckBoxColumn Binding="{Binding isChecked}" />
<DataGridTextColumn Header="Note" Binding="{Binding note}" Width="Auto"/>
<DataGridTextColumn Header="No" Binding="{Binding no}" Width="Auto"/>
<DataGridTextColumn Header="English Note" Binding="{Binding eng}" Width="Auto"/>
<DataGridTextColumn Header="German Note" Binding="{Binding deu}" Width="Auto"/>
</DataGrid.Columns>
</DataGrid>
</TabItem>
</TabControl>
</Grid>
</Window>
Model Class:
class viewModelObj : INotifyPropertyChanged
{
public string displayName { get; set; }
private List<ExcelDataEntry> _generalNoteList;
public List<ExcelDataEntry> generalNoteList
{
get { return _generalNoteList; }
set
{
_generalNoteList = value;
OnPropertyChanged("generalNoteList");
MessageBox.Show($"generalNoteList changed from model.");
}
}
public viewModelObj(string name)
{
displayName = name;
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
}
View Model Class
class ChangeRequestViewModel
{
public ObservableCollection<ExcelDataEntry> generalNoteSource { get; set; } = new ObservableCollection<ExcelDataEntry>();
public ObservableCollection<viewModelObj> viewModelSource { get; set; } = new ObservableCollection<viewModelObj>();
public ChangeRequestViewModel()
{
List<ExcelDataEntry> dataPool = Default.GenerateDataPool("data.xlsx", 1, 4, 1, 71, 5);
foreach (var entry in dataPool.Where(x => x.note == "GN").ToList())
{
this.generalNoteSource.Add(entry);
}
CatDocFactory catDocFactory = new CatDocFactory();
foreach (var entry in catDocFactory.GetAllOpenedDocs())
{
this.viewModelSource.Add(new viewModelObj(entry.displayName));
}
}
}
Class for data displayed in the Datagird:
public class ExcelDataEntry
{
public bool isChecked { get; set; }
public string note { get; set; }
public ExcelDataEntry(string note)
{
this.isChecked = false;
this.note = note;
}
}
Main.cs:
public partial class MainWindow : Window
{
Window parentWindow;
private ChangeRequestViewModel changeRequestDataContext;
public MainWindow(Window window)
{
InitializeComponent();
parentWindow = window;
parentWindow.Visibility = Visibility.Hidden;
LoadDefaultData();
}
private void LoadDefaultData()
{
changeRequestDataContext = new ChangeRequestViewModel();
}
private void export_Click(object sender, RoutedEventArgs e)
{
List<CatDocumentInView> output = changeRequestDataContext.viewModelSource.ToList();
}
}
As you can see, in my design, each row in the Datagrid represents a class. Ideally is, when the checkbox in the first column is checked, the instance representing this row will be added in the List<ExcelDataEntry> generalNoteList
of an instance of the class viewModelObj and vise versa. But this step confuses me how to deal with binding.
Could someone help me with this? Maybe my design is wrong and I should find another method to reach such requirement? Or I should change the structure of the Datagrid?
Hi,
You can check this article with example code.
https://www.c-sharpcorner.com/UploadFile/33b051/delete-multiple-record-from-a-datagridview-using-checkbox-i/