I have a Datagrid as follows
<DataGridTextColumn Header="Amount" CellStyle="{StaticResource RightAlignedCellStyle}" Binding="{Binding AmountToAllocate, UpdateSourceTrigger=LostFocus, StringFormat='{}{0:#,0.00}'}" />
<DataGridTemplateColumn Header="Comment" Width="*" IsReadOnly="True">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Comment}" TextWrapping="WrapWithOverflow"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Content="Add This Allocation" Command="ac:PICommands.AddAllocation" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
You will see that the ItemSource of the Grid is the property RenewalRows which is an ObservableCollection as follows:-
public ObservableCollection<Data.Payment.UnitRenewalsRow> RenewalRows
{
get
{
return renewalRows;
}
set
{
renewalRows = value;
OnPropertyChanged("RenewalRows");
}
}
SelectedItem is bound to the SelectedRenewalRow property as follows:-
public Data.Payment.UnitRenewalsRow SelectedRenewalRow
{
get
{
return renewalsRow;
}
set
{
renewalsRow = value;
//FullAllocationAmount();
OnPropertyChanged("SelectedRenewalRow");
}
}
There is a button in the last column which calls a command. The code behind as follows:-
private void Allocate(object sender, ExecutedRoutedEventArgs e)
{
ap.AddAnAllocation();
}
ap is the StaticResource class referred in the DataGrid ItemsSource="{Binding Source={StaticResource AllocatePaymentClass}, Path=RenewalRows}”
The code is as follows:-
public void AddAnAllocation()
{
SelectedRenewalRow.Outstanding = SelectedRenewalRow.Outstanding + SelectedRenewalRow.AmountToAllocate;
Allocation allocation = new Allocation();
allocation.Amount = SelectedRenewalRow.AmountToAllocate;
allocation.PaymentInfo = Payment;
allocation.RenewalInfo = SelectedRenewalRow;
allocation.Propref = PropRef;
allocation.FullAddress = FullAddress;
Allocations.Add(allocation);
Payment.Allocations = Allocations;
//reset
SelectedRenewalRow.AmountToAllocate = 0;
}
My problem is the last line. As soon as the user clicks the button that calls AddAnAllocation() I would like the screen to immediately update the selected row in the DataGrid with the AmountToAllocate Property to show as zero. The property is a field on the items in the RenewalRows property shown above. The screen eventually does update but only after the row has been deselected and then reselected and then sometimes even only if a few seconds have gone by.
Any ideas? If you need any further information or code please feel free to ask.
Im not sure if this is any help but it seems using DataTables + DataRows may have caused issues with other people in the past.
Have a look here
and here
Related
When my aapp launched i read a pricing file method attached to the soource using viewm-model approach then display it to the datagrid.
I'm trying to read the pricing file when i click on a button then attach the method to the view source.
I tried to set the view source on button click but nothing is displayed in the datagrid? thanks for your help.
case "ReadPricing": //to read local pricing file
cvs.Source = GetProductsPriceListXML(); // method to read the xml file
cvs.View.Filter = Filter;
View = cvs.View;
return;
Button:
<Button x:Name="breadxml" HorizontalAlignment="Center" Margin="62,10" Width="76" Command="{Binding MyCommand}" CommandParameter="ReadPricing" Height="43" >
<TextBlock Text="Read Pricing File" TextWrapping="Wrap" TextAlignment="Center"/>
</Button>
Datagrid:
<DataGrid VerticalAlignment="Top" HorizontalAlignment="Left"
SelectedItem="{Binding SelectedProduct}"
ItemsSource="{Binding View}" AutoGenerateColumns="False"
CanUserAddRows="False" ScrollViewer.VerticalScrollBarVisibility="Visible"
Margin="0,2,0,0"
Height="{Binding RelativeSource={RelativeSource AncestorType={x:Type DockPanel}}, Path=ActualHeight}" >
<DataGrid.Columns>
<DataGridTextColumn Header="MianProduct" Binding="{Binding Mainproduct}" Width="*" IsReadOnly="True"/>
<DataGridTextColumn Header="Name" Binding="{Binding Name}" Width="*" IsReadOnly="True"/>
<DataGridTextColumn Header="Price" Binding="{Binding Price}" Width="*" />
<!--<DataGridTextColumn Header="Visible" Binding="{Binding Visible}" Width="*" />-->
<DataGridTemplateColumn Header="Visible" Width="100" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding Visible, UpdateSourceTrigger=PropertyChanged}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="NameIcon" Binding="{Binding NameIcon}" Width="*" />
</DataGrid.Columns>
</DataGrid>
Datacontext/convertor:
<Window.DataContext>
<local:ProductPriceViewModel/>
</Window.DataContext>
<Window.Resources>
<local:MediaConverter x:Key="mconv" />
</Window.Resources>
Class-ViewModel:
class ProductPriceViewModel : INotifyPropertyChanged
{
public ProductPriceViewModel() { }
public event PropertyChangedEventHandler PropertyChanged;
public event EventHandler? CanExecuteChanged;
public void OnPropertyChanged([CallerMemberName] String info = "") =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(info));
private bool Filter(object item)
{
Product p = item as Product;
if (p == null) return true;
var ret = true;
if (!String.IsNullOrEmpty(MainProductSearch))
ret = ret && p.Mainproduct.IndexOf(MainProductSearch, StringComparison.OrdinalIgnoreCase) >= 0 ||
p.Name.IndexOf(MainProductSearch, StringComparison.OrdinalIgnoreCase) >= 0;
return ret;
}
private CollectionViewSource cvs = new CollectionViewSource();
public ICollectionView View { get; set; }
public ICommand MyCommand { get => new RelayCommand(executemethod, canexecutemethod); }
string pricinglocalfile = #"C:\xmltest\Prices.txt";
private void executemethod(object parameter)
{
switch (parameter.ToString())
{
case "ReadPricing": //to read local pricing file
cvs.Source = GetProductsPriceListXML();
return;
case "SaveFile":
data.Save("xxx.txt");
return;
default:
MediaType = parameter.ToString();
break;
}
View.Refresh();
}
private static bool canexecutemethod(object obj) => true;
XElement data;
private List<Product> GetProductsPriceListXML()
{
var mylist = new List<Product>();
data = XElement.Load(pricinglocalfile);
foreach (XElement xe1 in data.Elements())
if (xe1.Name == "Products")
foreach (var xe2 in xe1.Elements()) mylist.Add(new Product(xe2));
return mylist;
}
}
Although I've not used it myself, reading through Microsoft documentation leads me to believe that CollectionView is actually a control that you can extend that allows you to manipulate a data collection within the UI without actually changing the data itself. It also doesn't appear to be used with DataGrid types but instead replaces them, specifically it expands upon or replaces ListView.
In this regard you need to bind your ItemSource to an actual data list e.g., ObservableCollection<Product>, whether you use a DataGrid type or a CollectionView type within your UI.
Thus I would recommend that you change the following:
private CollectionViewSource cvs = new CollectionViewSource();
public ICollectionView View { get; set; }
to
public ObservableCollection<Product> ProductList {get;set;}
This will automatically trigger a NotifyCollectionChanged when updated.
Then change :
case "ReadPricing": //to read local pricing file
cvs.Source = GetProductsPriceListXML();
return;
to
case "ReadPricing": //to read local pricing file
ProductList.Clear();
var list = GetProductsPriceListXML();
foreach(var p in list)
{
ProductList.Add(p);
}
return;
or
case "ReadPricing": //to read local pricing file
ProductList = new ObservableCollection<Product>(GetProductsPriceListXML());
NotifyPropertyChanged("ProductList");
return;
Then in your View
ItemsSource="{Binding View}" AutoGenerateColumns="False"
becomes
ItemsSource="{Binding ProductList}" AutoGenerateColumns="False"
I believe that if you then wished to manipulate the layout or content of your ProductList at run time you would need to replace your DataGrid with a CollectionView, bind it's ItemSource to ProductList, finally creating a ControlView that presents a CollectionView type property and manipulates the presentation of the data - examples to be found here
In my WPF application using MVVM, I have one DataGrid (dgSelectCase) filled with a bound ObservableCollection from my ViewModel. A Button appears in the first column that, when clicked, should add the selected row to the second DataGrid (dgCaseSelected).
The View DataContext is bound to the ViewModel in its code behind, and I know it works because the other Controls on the page (Comboboxes, Textboxes, etc.) work perfectly. The "Add" Button Command in dgSelectCase is bound to the AddTo method in the ViewModel and the "Remove" Button Command in dgCaseSelected is bound to the RemoveFrom method in the ViewModel.
The "Add" Button is not working, but, more importantly, it looks like I have selection Binding issues in the dgSelectCase DataGrid because I get a red box around the DataGrid when I click on a row. Where have I gone wrong? Thanks for any and all help, as I'm still learning.... slowly :). Following are Code Snippets.
XAML
<DataGrid>
<DataGrid.Columns>
<DataGridTemplateColumn Header="Select">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Content="Add" Command="{Binding AddTo}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="Fac ID #" Binding="{Binding FacilityIDNum}"/>
<DataGridTextColumn Header="OP Case #" Binding="{Binding CaseBookingNum}"/>
<DataGridTextColumn Header="Booking Type #" Binding="{Binding BookingTypeNum}"/>
<DataGridTextColumn Header="Booking Type" Binding="{Binding BookingType}"/>
</DataGrid.Columns>
</DataGrid>
<DataGrid x:Name="dgCaseSelected"
AutoGenerateColumns="False"
ItemsSource="{Binding DGCaseBookingsSelected}"
>
<DataGrid.Columns>
<DataGridTemplateColumn Header="Select">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Content="Remove" Command="{Binding RemoveFrom}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="Fac ID #" Binding="{Binding FacilityIDNum}"/>
<DataGridTextColumn Header="OP Case #" Binding="{Binding CaseBookingNum}"/>
<DataGridTextColumn Header="Booking Type #" Binding="{Binding BookingTypeNum}"/>
<DataGridTextColumn Header="Booking Type" Binding="{Binding BookingType}"/>
</DataGrid.Columns>
</DataGrid>
VIEWMODEL
private ObservableCollection<DGCaseBookings> _dgCaseBookingsList;
private ObservableCollection<DGCaseBookings> _dgSelectedCaseBookings;
private ObservableCollection<DGCaseBookings> _dgCaseBookingsSelected;
public ObservableCollection<DGCaseBookings> DGCaseBookingsList
{
get { return _dgCaseBookingsList; }
set
{
SetProperty(ref _dgCaseBookingsList, value, () => DGCaseBookingsList);
}
}
public ObservableCollection<DGCaseBookings> DGSelectedCaseBookings
{
get { return _dgSelectedCaseBookings; }
set
{
SetProperty(ref _dgSelectedCaseBookings, value, () => DGSelectedCaseBookings);
}
}
public ObservableCollection<DGCaseBookings> DGCaseBookingsSelected
{
get { return _dgCaseBookingsSelected; }
set
{
SetProperty(ref _dgCaseBookingsSelected, value, () => DGCaseBookingsSelected);
}
}
public CMBookingSelectVM() : base()
{
DGCaseBookingsList = new ObservableCollection<DGCaseBookings>();
DGCaseBookingsSelected = new ObservableCollection<DGCaseBookings>();
}
private void fillDGCaseBookingswithFacility()
{
using (MySqlConnection con = new MySqlConnection(dbConnectionString))
{
DGCaseBookingsList = new ObservableCollection<DGCaseBookings>();
con.Open();
string Query = ///SELECT STATEMENT WORKS FINE///
MySqlCommand createCommand = new MySqlCommand(Query, con);
MySqlDataReader dr = createCommand.ExecuteReader();
int count = 1;
while (dr.Read())
{
int FacilityIDNum = dr.GetInt32(0);
int CaseBookingNum = dr.GetInt32(1);
int BookingTypeNum = dr.GetInt32(2);
string BookingType = dr.GetString(3);
DGCaseBookings dgcb = new DGCaseBookings(count, FacilityIDNum, CaseBookingNum, BookingTypeNum, BookingType);
DGCaseBookingsList.Add(dgcb);
count++;
}
con.Close();
}
}
public void AddTo(DGCaseBookings dgcb)
{
if (dgcb != null)
{
DGCaseBookingsSelected.Add(dgcb);
DGCaseBookingsList.Remove(dgcb);
}
}
public void RemoveFrom(DGCaseBookings dgcb)
{
if (dgcb != null)
{
DGCaseBookingsList.Add(dgcb);
DGCaseBookingsSelected.Remove(dgcb);
}
}
First of all, you didn't mentioned in your code how you are trying to bind the selected items property of the datagrid to your collection (as a matter of facts you are actually didn't even set the itemsource for the first datagrid), and i think you didn't do that since you actually can't bind the SelectedItems property of the datagrid since it's a readonly property. From now on you have only 2 choice. Find a workaround to send the selected items to your viewmodel, or work on a single row. As for the second approach you can simply do this:
<DataGrid ItemsSource="{Binding DGCaseBookingsList}" SelectedItem="{Binding MyItem}" SelectionMode = "Single" SelectionUnit="FullRow">
<DataGrid.Columns>
<DataGridTemplateColumn Header="Select">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Content="Add" Command="{Binding AddTo}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="Fac ID #" Binding="{Binding FacilityIDNum}"/>
<DataGridTextColumn Header="OP Case #" Binding="{Binding CaseBookingNum}"/>
<DataGridTextColumn Header="Booking Type #" Binding="{Binding BookingTypeNum}"/>
<DataGridTextColumn Header="Booking Type" Binding="{Binding BookingType}"/>
</DataGrid.Columns>
</DataGrid>
in your VM delete DGSelectedCaseBookings and add the following:
private DGCaseBookings myItem = new DGCaseBookings();
public DGCaseBookings MyItem
{
get { return myItem; }
set
{
SetProperty(ref myItem, value, () => MyItem);
}
}
From there you will handle this object using the command of your buttons. Just be sure to implement INotifyPropertyChanged or you won't see any change in your UI.
If you aim to a multiple selection, then the easiest way is to work on the selection changed event of your datagrids. From there you can do something like this.
private void DataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
MyVM vm = this.DataContext as MyVM;
DataGrid s = sender as DataGrid;
vm.DGSelectedCaseBookings = s.SelectedItems;
}
In background of this you can setup the event when you click on button and add the current row (like param of the event). Take the current row select it from the datasource/ObservableCollection and add it in another dataset e.g _dgSelectedCaseBookings.
After that you can refresh the new _dgSelectedCaseBookings on UI.
I was not able to use the answers from other similar questions. I feel I'm close to a solution, but struggle on one or two points.
I need a ComboBoxColumn in my DataGrid.
the ComboBoxColumn shows defaultly the place where an item is stocked right now.
I should be able to change the place with the ComboBox.
Here is the DataGrid with the ComboBox included:
<DataGrid x:Name="goederenZoekenDataGrid"
AutoGenerateColumns="False"
EnableRowVirtualization="True"
ItemsSource="{Binding}"
Margin="10,315,10,120"
RowDetailsVisibilityMode="VisibleWhenSelected"
RowEditEnding="goederenZoekenDataGrid_RowEditEnding">
<DataGrid.Columns>
<DataGridTextColumn x:Name="lotnummerLeverancierColumn"
Binding="{Binding LotnummerLeverancier}"
Header="Lotnr Leverancier" Width="auto"/>
<DataGridTextColumn x:Name="grondstofomschrijvingColumn"
Binding="{Binding Grondstofomschrijving}"
Header="Grondstof" Width="auto"/>
<DataGridTextColumn x:Name="leveranciersNaamColumn"
Binding="{Binding LeveranciersNaam}"
Header="Leverancier" Width="auto"/>
<DataGridTemplateColumn x:Name="datumLeveringColumn"
Header="Datum Levering" Width="auto">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<DatePicker SelectedDate="{Binding DatumLevering, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn x:Name="hoeveelheidGeleverdColumn"
Binding="{Binding HoeveelheidGeleverd}"
Header="Hoeveelheid IN" Width="auto"/>
<DataGridTextColumn x:Name="eenheidColumn"
Binding="{Binding Eenheid}"
Header="Eenheid" Width="auto"/>
<DataGridTextColumn x:Name="lotnummerINIDColumn"
Binding="{Binding LotnummerINID}"
Header="Lotnummer INID" Width="auto"/>
<DataGridTemplateColumn x:Name="stockINOmschrijvingColumn"
Header="Stockplaats IN" Width="auto">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox Name="cmbStockINGrid"
Text="{Binding StockINOmschrijving, Mode=Twoway, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}"
IsEditable="True" Height="20"
SelectionChanged="cmbStockINGrid_SelectionChanged"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn x:Name="HoeveelheidStockINColumn"
Binding="{Binding HoeveelheidStockIN}"
Header="Hoeveelheid Stock" Width="auto"/>
</DataGrid.Columns>
</DataGrid>
This gives me already the result of the stock place. Good sign. But to fill the ComboBox up with the rest of all the places I must have made a mistake since no result is returned. My biggest struggle here is the fact that the ComboBox name used in the DataGridTemplateColumn.CellTemplate couldn't be used in the code behind.
private void cmbStockINGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ComboBox combostockIN = (ComboBox)sender;
stockPlaatsINViewSource = ((System.Windows.Data.CollectionViewSource)(this.FindResource("stockPlaatsINViewSource")));
var manager = new LotnummersDBManager();
using (var conLotnrs = manager.Getconnection())
using (var comstockin = conLotnrs.CreateCommand())
{
comstockin.CommandType = CommandType.Text;
comstockin.CommandText = "SELECT StockINOmschrijving FROM StockPlaatsIN order by StockINOmschrijving asc";
conLotnrs.Open();
using (var rdrstockin = comstockin.ExecuteReader())
{
while (rdrstockin.Read())
{
combostockIN.Items.Add(rdrstockin[0]);
}//while
} //using rdrStockPlaatsIN
}//using Conlotnrs and ComStockPlaatsIN
}// cmbStockINGrid_SelectionChanged
Result is in Can anyone help me out to fill the ComboBox with the selection from sql?
My StockPlaatsINViewsource comes from the following class:
namespace AdoGemeenschap
{
public class StockPlaatsIN : LotnummerIN
{
private Int32 stockplaatsinidValue;
private String stockinValue;
private decimal HoeveelstockinValue;
public Int32 StockPlaatsINID
{
get { return stockplaatsinidValue; }
set { stockplaatsinidValue = value; }
}
public String StockINOmschrijving
{
get { return stockinValue; }
set { stockinValue = value; }
}
public decimal HoeveelheidStockIN
{
get { return HoeveelstockinValue; }
set { HoeveelstockinValue = value; }
}
public StockPlaatsIN(Int32 stockinID, String stockbeschrijving, decimal hoeveelstockin, Int32 lotnrinid):base(lotnrinid)
{
this.StockPlaatsINID = stockinID;
this.StockINOmschrijving = stockbeschrijving;
this.StockINOmschrijving = stockbeschrijving;
this.HoeveelheidStockIN = hoeveelstockin;
}
public StockPlaatsIN(string stockbeschrijving)
{
this.StockINOmschrijving = stockbeschrijving;
}
}
PS: Other possibility that I tried was as follows but I don't even find how to use a ComboBox:
<DataGridComboBoxColumn x:Name="stockINOmschrijvingColumn"
Header="Stockplaats IN" Width="auto"
SelectedItemBinding="{Binding StockINOmschrijving, Mode=TwoWay}"
ItemsSource="{Binding Source={StaticResource stockPlaatsINViewSource}}"/>
I got a data grid which includes a check box column. I made a modification to that form by using a multiselect checkbox to check all rows at once. And it worked. but i was unable to get the value from that checkbox column when the app is running because i was not sure how to access the data column. can anyone help me with a way to get the check box value (true/false).
This is what i did so far.
Code: xaml
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Path= Id}" Header="Id" Visibility="Hidden"/>
<DataGridTextColumn Binding="{Binding Path= Category}" Header="Category" Width="320"/>
<!--<DataGridCheckBoxColumn Binding="{Binding Path= Check}" Width="*"/>-->
<DataGridTemplateColumn>
<DataGridTemplateColumn.Header>
<CheckBox x:Name="headerCheckBox" />
</DataGridTemplateColumn.Header>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox Name="chkSelectAll" HorizontalAlignment="Center" IsChecked="{Binding IsChecked, ElementName=headerCheckBox, Mode=OneWay}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
Code: C#
for (int i = 0; i < datagridview.Items.Count; i++)
{
ÇategoryData CD = (ÇategoryData)datagridview.Items[i];
if (CD.Check == true)
{
//it always returns false even checked
}
}
First of all, I fail to see what that value would be used for? I mean, the checkbox acts like a UI mechanism to select or unselect all the other boxes. But even if you actually need the value, why don't you bind it twoway to a ViewModel property?
Like this:
<CheckBox x:Name="headerCheckBox" Value="{Binding SelectAllCheckboxInTheViewModel}" />
Here are many things kind of weird in my opinion.
I don't really get why your rows' Checkbox is called "chkSelectAll"
I suggest you try to get the following: Each Checkbox can be Checked,UnChecked by themself. When you hit the Headers Checkbox, then all Columns Checkbox get the same State (Checked if at least one was unchecked, and Unchecked if ALL Rows Checkboxes were checked).
If that is right, than you should do the following:
As Siderite Zackwehdex mentioned (I thing that he meant that), you should bind the Checkbox IsChecked Value to a Property of the underlying ViewModel of the Row.
Than your Headers Checkbox should be also bind to a Property of the Viewmodel which holds the Observable Collection like the following:
public bool AllSelected
{
get { return !this.MyCollection.Any(item => !item.IsSelected); }
set
{
var toggle = this.MyCollection.Any(item => !item.IsSelected);
foreach (var itm in this.MyCollection.Where(item => item.IsSelected != toggle))
itm.IsSelected = toggle;
}
}
The IsSelected-Property-Setter of the Collections Items-ViewModel MUST notify the ParentViewModel (which holds the Collection) that one IsSelected/IsChecked (however you want to call it) State has changed. So that a PropertyChanged Event for PropertyName "AllSelected" will be raised.
The Collection Items ViewModel Property could look like this:
public bool IsSelected
{
get { return _isSelected; }
set
{
_isSelected = value;
RaisePropertyChanged("IsSelected");
ParentViewModel.RaisePropertyChanged("IsSelected");
}
}
Both CheckBoxes (The one in the Header Template and the one in the CellTemplate) are bind with Mode=Twoway
I know this isn't necessarily specific to MahApps Metro DataGridCheckBoxColumns, but I figured that information may help someone answer my question.
I'm trying to do two things with my DataGridCheckBox Column in MahApps Metro
1. I would like to have two separate datagrids, and have the ability to return the value in the second column of whichever row is selected
For example, if I had a datagrid that looked like this:
When someone has the checkbox associated with 2 selected, and the checkbox associated with Red selected, I would like a messagebox to show "2 Red".
my .xaml
<DataGrid Name="numberGrid"
ItemsSource="{Binding Path=numberGrid}"
Grid.Row="0"
AutoGenerateColumns="False"
Width="300"
Height="auto">
<DataGrid.Columns>
<DataGridCheckBoxColumn ElementStyle="{DynamicResource MetroDataGridCheckBox}"
EditingElementStyle="{DynamicResource MetroDataGridCheckBox}"
Header="Select"
Binding="{Binding RelativeSource={RelativeSource AncestorType=DataGridRow}, Path=IsSelected, Mode=OneWay}"
/>
<DataGridTextColumn Header="Numbers"
Binding="{Binding Number, Mode=OneWay}"
Width="*"/>
</DataGrid.Columns>
</DataGrid>
<DataGrid Name="colorGrid"
ItemsSource="{Binding Path=colorGrid}"
Grid.Row="0"
AutoGenerateColumns="False"
Width="300">
<DataGrid.Columns>
<DataGridCheckBoxColumn ElementStyle="{DynamicResource MetroDataGridCheckBox}"
EditingElementStyle="{DynamicResource MetroDataGridCheckBox}"
Header="Select"
Binding="{Binding RelativeSource={RelativeSource AncestorType=DataGridRow}, Path=IsSelected, Mode=OneWay}"
/>
<DataGridTextColumn Header="Colors"
Binding="{Binding Color, Mode=OneWay}"
Width="*"/>
</DataGrid.Columns>
</DataGrid>
my .cs with the pseudocode of what I think should happen commented out.
ObservableCollection<MahAppsNumbers> MAnumbers = new ObservableCollection<MahAppsNumbers>
{
new MahAppsNumbers{Number = "1"},
new MahAppsNumbers{Number = "2"},
new MahAppsNumbers{Number = "3"},
new MahAppsNumbers{Number = "4"}
};
public class MahAppsNumbers
{
public string Number { set; get; }
}
ObservableCollection<MahAppsAccents> MAcolors = new ObservableCollection<MahAppsColors>
{
new MahAppsColors{Color = "Red"},
new MahAppsColors{Color = "Orange"},
new MahAppsColors{Color = "Yellow"},
new MahAppsColors{Color = "Green"}
};
public class MahAppsColors
{
public string Color { set; get; }
}
public myWindow()
{
InitializeComponent();
numberGrid.ItemsSource = MAnumbers;
colorGrid.ItemsSource = MAcolors;
//Something like this maybe? I know this isn't a thing you can do
//string currentNumber = numberGrid.SelectedRow[1]; //to get the second column value
//string currentColor = colorGrid.SelectedRow[1];
//MessageBox.Show(currentNumber + currentColor);
}
2. For bonus points, why do I have an extra row at the end?
I've found TONS of solutions for this, that are all basically the same. But that doesn't solve my problem.
Thanks in advance.
Edit 1
Since I want this even to happen every time a box is selected, I'm trying something like this inside of myWindow()
this.numberGrid.SelectedCellsChanged += new SelectedCellsChangedEventHandler(numberGrid_SelectionChanged);
and adding a function that hopefully someone can point me in the right direction to fixing.
private void numberGrid_SelectionChanged(object sender, SelectedCellsChangedEventArgs e)
{
MessageBox.Show(numberGrid.SelectedItem.ToString());
}
Try Binding like this,
<DataGridCheckBoxColumn Binding="{Binding Path=IsSelected, Mode=TwoWay}" />
Now you have a Property IsSelected add this to your collection which binds your DataGrid. When you check your CheckBox IsSelected property Set will call and set it to True, now in your collection has the IsSelected True for which its checked.