I want to Refresh my DataGrid and found the following coding on the web:
dataGridView.ItemsSource = null;
dataGridView.ItemsSource = ItemsSourceObjects;
It does work except for the string/column Names does not get displayed with the objects only the objects/items itself.
Any Ideas on why this is happening?
EDIT:
<DataGridTextColumn Binding="{Binding TId}" Header="id" MinWidth="20" MaxWidth="60"/>
<DataGridTextColumn Binding="{Binding TChassisManufacturer}" Header="Project Name" MinWidth="122" MaxWidth="200"/>
<DataGridTextColumn Binding="{Binding ProjectStatusM}" Header="Status" MinWidth="122" MaxWidth="100"/>
Here is an example:
You don't need to call refresh. When you add/delete items from my, dg will auto update for you.
XAML:
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1">
<DataGrid Name="dataGridView" ItemsSource="{Binding}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding TId}" Header="id" MinWidth="20" MaxWidth="60"/>
<DataGridTextColumn Binding="{Binding TChassisManufacturer}" Header="Project Name" MinWidth="122" MaxWidth="200"/>
<DataGridTextColumn Binding="{Binding ProjectStatusM}" Header="Status" MinWidth="122" MaxWidth="100"/>
</DataGrid.Columns>
</DataGrid>
</Window>
C#:
public partial class MainWindow : Window
{
ObservableCollection<myClass> my = new ObservableCollection<myClass>();
public MainWindow()
{
InitializeComponent();
dataGridView.DataContext = my;
my.Add(new myClass { TId = 1, TChassisManufacturer = "Sony", ProjectStatusM = "Done" });
my.Add(new myClass { TId = 2, TChassisManufacturer = "Apple", ProjectStatusM = "Doing" });
}
}
class myClass : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
int id;
public int TId
{
get
{
return id;
}
set
{
id = value;
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("TId"));
}
}
string name;
public string TChassisManufacturer
{
get
{
return name;
}
set
{
name = value;
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("TChassisManufacturer"));
}
}
string status;
public string ProjectStatusM
{
get
{
return status;
}
set
{
status = value;
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("ProjectStatusM"));
}
}
}
Related
So I got a WPF datagrid which is created like this:
<DataGrid x:Name="columns" Grid.Row="1" HorizontalContentAlignment="Stretch" HorizontalAlignment="Stretch" ItemsSource="{Binding}" DataContext="{StaticResource ColumnsCollection}"
AutoGenerateColumns="False" CanUserAddRows="True" CanUserDeleteRows="True" AddingNewItem="columns_AddingNewItem">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding Name}" Width="Auto"/>
<DataGridTextColumn Header="Width of Name" Binding="{Binding WidthOfNameInCentimeter}" Width="Auto"/>
</DataGrid.Columns>
</DataGrid>
it is initialized like this:
CollectionViewSource itemCollectionViewSource;
itemCollectionViewSource = (CollectionViewSource)(FindResource("ColumnsCollection"));
itemCollectionViewSource.Source = new ObservableCollection<FormCreatorColumnInfoDatasource>();
and populated.
The FormCreatorColumnInfoDatasource looks like this:
class FormCreatorColumnInfoDatasource : INotifyPropertyChanged
{
private IFormCreatorColumnInfo m_info;
public string Name
{
get
{
return m_info.Name;
}
set
{
m_info.Name = value;
}
}
public string WidthOfNameInCentimeter
{
get
{
var exactWidthInCentimeter = Name.Length * 0.238M;
var roundedUpToHalfCentimeter = Math.Round(exactWidthInCentimeter * 2, MidpointRounding.AwayFromZero) / 2;
return (roundedUpToHalfCentimeter).ToString();
}
}
}
So now I want to instantly change the content of the column WidthOfNameInCentimeter (Width of Name) when the user manually changes the Name of the column so there is always the correct information in this column.
How do I do this?
With the help of #lidqy I added a function and changed the setter of Name:
class FormCreatorColumnInfoDatasource : INotifyPropertyChanged
{
private IFormCreatorColumnInfo m_info;
public string Name
{
get
{
return m_info.Name;
}
set
{
m_info.Name = value;
OnPropertyChanged(nameof(Name));
OnPropertyChanged(nameof(WidthOfNameInCentimeter));
}
}
public string WidthOfNameInCentimeter
{
get
{
var exactWidthInCentimeter = Name.Length * 0.238M;
var roundedUpToHalfCentimeter = Math.Round(exactWidthInCentimeter * 2, MidpointRounding.AwayFromZero) / 2;
return (roundedUpToHalfCentimeter).ToString();
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string property)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
Dont forget to implement INotifyPropertyChanged in the datasource and to use an ObservableCollection for the datagrids source.
Well, I have a data class with some data objects like this:
private ObservableCollection<bool> check = new ObservableCollection<bool>();
public ObservableCollection<bool> Check
{
get { return check; }
set
{
check = value;
Notify("check");
}
}
private ObservableCollection<string> user = new ObservableCollection<string>();
public ObservableCollection<string> User
{
get { return user; }
set
{
user = value;
Notify("user");
}
}
And in the MainWindow I added a DataGrid like this:
<DataGrid AutoGenerateColumns="False"
Name="dataGrid1"
CanUserAddRows="False" CanUserSortColumns="False" CanUserResizeColumns="True" CanUserReorderColumns="False"
ItemsSource="{Binding}">
<DataGrid.Columns >
<DataGridCheckBoxColumn Header = "" Binding="{Binding Check, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" MinWidth="50" />
<DataGridTextColumn Header = "User" Binding="{Binding User, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" MinWidth="50" />
</DataGrid.Columns>
</DataGrid>
For the whole Window the datakontext ist set to the data class. In the constructor I called "DataContext = theData"; I added some values in the constructor of the data class and proofed by running the program the instance of this class. The values are correct added to the ObservableCollection.
But the values are not shown in the datagrid. Why?
The ItemsSource property of the DataGrid should be set or bound to an IEnumerable<T>. And a single column in the DataGrid should be bound to a property of the type T. You are trying to bind a DataGridTextColumn to an ObservableCollection<string> and a DataGridCheckBoxColumn to an ObservableCollection<bool> and this makes no sense. They should be bound to a string and bool property respectively. Please refer to the following sample code.
Model:
public class YourDataObject : INotifyPropertyChanged
{
private bool _check;
public bool Check
{
get { return _check; }
set { _check = value; NotifyPropertyChanged(); }
}
private string _user;
public string User
{
get { return _user; }
set { _user = value; NotifyPropertyChanged(); }
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
View Model:
public class ViewModel
{
public ViewModel()
{
TheDataObjects = new ObservableCollection<YourDataObject>();
TheDataObjects.Add(new YourDataObject());
TheDataObjects.Add(new YourDataObject());
TheDataObjects.Add(new YourDataObject());
}
public ObservableCollection<YourDataObject> TheDataObjects { get; private set; }
}
View:
public MainWindow()
{
InitializeComponent();
DataContext = new ViewModel();
}
<DataGrid AutoGenerateColumns="False"
Name="dataGrid1"
CanUserAddRows="False" CanUserSortColumns="False" CanUserResizeColumns="True" CanUserReorderColumns="False"
ItemsSource="{Binding TheDataObjects}">
<DataGrid.Columns >
<DataGridCheckBoxColumn Header = "" Binding="{Binding Check, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" MinWidth="50" />
<DataGridTextColumn Header = "User" Binding="{Binding User, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" MinWidth="50" />
</DataGrid.Columns>
</DataGrid>
Try setting,
this.DataContext = theData;
You need to set proper property to ItemsSource.
ItemsSource="{Binding User}"
Above line will clear the issue.
Also, you should Notify public properties in Setter.
Notify("Check");
Notify("User");
I am developing a wpf application and i have a "buyer" named datagrid and i want access row values when a checkbox is checkedI have read some questions on stackoverflow but all went over my head, i was not able to understand them as amatuer yet :( Here is my datagrid xaml code:-
<DataGrid x:Name="buyer" SelectionMode="Single" HorizontalAlignment="Left" SelectionUnit="FullRow" VerticalAlignment="Top" Height="550" Width="992" HorizontalScrollBarVisibility="Visible" IsReadOnly="True" AutoGenerateColumns="False" FrozenColumnCount="1" Margin="0,45,0,0" SelectionChanged="RowFocus" TargetUpdated="buyer_TargetUpdated">
<DataGrid.Columns>
<DataGridTemplateColumn Header="Joining" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsSelected,UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="ID" Binding="{Binding buy_id}"/>
<DataGridTextColumn Header="Name" Binding="{Binding bname}"/>
<DataGridTextColumn Header="Number" Binding="{Binding mobileno}"/>
</DataGrid.Columns>
</DataGrid>
I have a button on the same window, which on clicking should give me values from the rows where the CheckBox is checked
Edit: Currently, I am checking if the CheckBox is working by writing in console. Also the CheckBox should be the 0th column, right? But when I print it in the console I get the value of the next column i.e. ID, I used to print the value by putting the following code :-
private void Button_Click_3(object sender, RoutedEventArgs e)
{
/* int i = 0;
Console.WriteLine("hey");
foreach (var item in buyer.Items)
{
string s = (buyer.Items[i] as DataRowView).Row.ItemArray[0].ToString();
if (i==0)
{
Console.WriteLine(s);
var row = buyer.ItemContainerGenerator.ContainerFromItem(item) as DataGridRow;
}
i++;
}*/
if (buyer.SelectedItems.Count > 0)
{
for (int i = 0; i < buyer.SelectedItems.Count; i++)
{
System.Data.DataRowView selectedFile = (System.Data.DataRowView)buyer.SelectedItems[i];
string str = Convert.ToString(selectedFile.Row.ItemArray[0]);
Console.WriteLine(str);
}
}
}
I used both commented and uncommented code
Try this.... (using RelayCommand found here http://www.kellydun.com/wpf-relaycommand-with-parameter/)
public class BasePropertyChanged : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
}
ViewModel.....
class Base_ViewModel : BasePropertyChanged
{
public RelayCommand<ObservableCollection<buyer>> ButtonClickCommand { get; set; }
private ObservableCollection<buyer> _buyer;
public ObservableCollection<buyer> buyer
{
get { return _buyer; }
set { _buyer = value; }
}
public Base_ViewModel()
{
ButtonClickCommand = new RelayCommand<ObservableCollection<buyer>>(OnButtonClickCommand);
buyer = new ObservableCollection<ViewModels.buyer>();
buyer.Add(new buyer() { buy_id = 1, bname = "John Doe", mobileno = "" });
buyer.Add(new buyer() { buy_id = 1, bname = "Jane Doe", mobileno = "" });
buyer.Add(new buyer() { buy_id = 1, bname = "Fred Doe", mobileno = "" });
buyer.Add(new buyer() { buy_id = 1, bname = "Sam Doe", mobileno = "" });
}
private void OnButtonClickCommand(ObservableCollection<buyer> obj)
{ // put a break-point here and obj will be the List of Buyer that you can then step though
}
}
Buyer Class.....
public class buyer : BasePropertyChanged
{
private bool _IsSelected;
public bool IsSelected
{
get { return _IsSelected; }
set { _IsSelected = value; }
}
private string _bname;
public string bname
{
get { return _bname; }
set { _bname = value; NotifyPropertyChanged("bname"); }
}
private int _buy_id;
public int buy_id
{
get { return _buy_id; }
set { _buy_id = value; NotifyPropertyChanged("buy_id"); }
}
private string _mobileno;
public string mobileno
{
get { return _mobileno; }
set { _mobileno = value; NotifyPropertyChanged("mobileno"); }
}
}
XAML.....
<StackPanel>
<DataGrid x:Name="buyer" ItemsSource="{Binding buyer}" SelectionMode="Single" HorizontalAlignment="Left" SelectionUnit="FullRow" IsReadOnly="True" AutoGenerateColumns="False" FrozenColumnCount="1" >
<DataGrid.Columns>
<DataGridTemplateColumn Header="Joining" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsSelected,UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="ID" Binding="{Binding buy_id}"/>
<DataGridTextColumn Header="Name" Binding="{Binding bname}"/>
<DataGridTextColumn Header="Number" Binding="{Binding mobileno}"/>
</DataGrid.Columns>
</DataGrid>
<Button Content="Button" Command="{Binding ButtonClickCommand}" CommandParameter="{Binding ElementName=buyer, Path=ItemsSource}" Margin="0,202,0,0"></Button>
</StackPanel>
And don't forget to set your DataContext in the View code-behind....
this.DataContext = new Base_ViewModel();
I have a datagrid where a user can enter some data. Once they have entered the data they click a button to upload the data. However I am having some issues with the data not binding as I expect.
The datagrid is bound to a list called HldLogEQ of type ObservableCollection HoldingLogEQ.
When I debug before the data is uploaded the ISIN and Sedol properties are both null which is incorrect. I thought the line below was the correct way to bind the data? What am I missing?
<DataGridTextColumn Header="Sedol" IsReadOnly="False" Binding="{Binding Security.Sedol, Mode=TwoWay}"/>
HoldingLoq Class
public class HoldingLogEQ : INotifyPropertyChanged
{
public DateTime DateEffective
{
get
{
return _dateEffective;
}
set
{
_dateEffective = value;
OnPropertyChanged("DateEffective");
}
}
public SecruityID Security
{
get
{
return _security;
}
set
{
_security = value;
OnPropertyChanged("Security");
}
}
public List<Fund> Funds
{
get
{
return _funds;
}
set
{
_funds = value;
OnPropertyChanged("Funds");
}
}
private DateTime _dateEffective;
private SecruityID _security = new SecruityDescriptive();
private List<Fund> _funds;
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
Security Id class
public class SecurityID : INotifyPropertyChanged
{
public string ISIN
{
get
{
return _isin;
}
set
{
_isin = value;
OnPropertyChanged("ISIN");
}
}
public string Sedol
{
get
{
return _sedol;
}
set
{
_sedol = value;
OnPropertyChanged("Sedol");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
private string _isin;
private string _sedol;
#endregion
}
Datagrid
<DataGrid Grid.Row="1"
x:Name="dgHldRGHTS"
ItemsSource="{Binding HldLogEQ, UpdateSourceTrigger=PropertyChanged}"
Style="{StaticResource DataGridTemplate1}"
ColumnHeaderStyle="{StaticResource DG_ColumnHeaderCenter1}"
RowStyle="{StaticResource DG_Row1}"
CellStyle="{StaticResource DG_Cell1}"
RowHeaderStyle="{StaticResource DG_RowHeader1}"
RowDetailsTemplate="{StaticResource DG_RowDetail}"
AutoGenerateColumns="False"
HorizontalAlignment="Stretch"
Background="Silver"
Margin="50,0,50,50"
CanUserDeleteRows="True"
CanUserAddRows="True"
RowHeaderWidth="30">
<DataGrid.Columns>
<DataGridTextColumn Header="Date Effective" IsReadOnly="False" Binding="{Binding DateEffective, StringFormat={}\{0:dd-MMM-yy\}, Mode=TwoWay}" MinWidth="75"/>
<DataGridTextColumn Header="ISIN" IsReadOnly="False" Binding="{Binding Security.ISIN, Mode=TwoWay}" MinWidth="75"/>
<DataGridTextColumn Header="Sedol" IsReadOnly="False" Binding="{Binding Security.Sedol, Mode=TwoWay}" MinWidth="75"/>
<DataGridTextColumn Header="Name" IsReadOnly="False" Binding="{Binding Security.Name, Mode=TwoWay}" MinWidth="200"/>
</DataGrid.Columns>
</DataGrid>
Maybe need add Path.
Binding="{Binding Path=Security.Sedol, Mode=TwoWay}"
I have implemented a DataGrid as follows:
<DataGrid Name="grdSignals" Grid.Column="1" ItemsSource="{Binding}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Signal Name" Binding="{Binding SignalName}"/>
<DataGridTextColumn Header="Value" Binding="{Binding SignalValue}" />
</DataGrid.Columns>
</DataGrid>
The following is the Class where I implemented the properties used in an ObservableCollection:
namespace Test
{
public partial class MyMain : UserControl
{
public ObservableCollection<Signals> ocSignalNames;
Signals time, mode;
public MyMain()
{
InitializeComponent();
ocSignalNames = new ObservableCollection<Signals>();
time = new Signals() { SignalName = "Time", SignalValue = "" };
mode = new Signals() { SignalName = "Mode", SignalValue = "" };
ocSignalNames.Add(time);
ocSignalNames.Add(mode);
grdSignals.DataContext = ocSignalNames;
}
}
public class Signals : INotifyPropertyChanged
{
string _signalName, _signalValue;
public string SignalName
{
get
{
return _signalName;
}
set
{
_signalName = value;
}
}
public string SignalValue
{
get
{
return _signalValue;
}
set
{
_signalValue = value;
OnPropertyChanged(SignalValue);
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
After debugging it, I found that the ocSignalNames is getting updated when its items change. But the changes are not getting reflected in the DataGrid. I am updating the Items in a thread like this:
time.SignalValue = iTest1.ToString();
mode.SignalValue = iTest2.ToString();
What am I missing out?
You are missing the correct NotifyChanged handlers:
public string SignalName
{
get
{
return _signalName;
}
set
{
_signalName = value;
OnPropertyChanged("SignalName"); //Added
}
}
public string SignalValue
{
get
{
return _signalValue;
}
set
{
_signalValue = value;
OnPropertyChanged("SignalValue"); //NOTE: quotation marks added
}
}
you have to use below mentioned code.
string _signalName, _signalValue;
public string SignalName
{
get
{
return _signalName;
}
set
{
_signalName = value;
OnPropertyChanged("SignalName");
}
}
public string SignalValue
{
get
{
return _signalValue;
}
set
{
_signalValue = value;
OnPropertyChanged(SignalValue);
}
}
your XAML look like
<DataGrid Name="grdSignals" Grid.Column="1" ItemsSource="{Binding}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Signal Name" Binding="{Binding SignalName, Mode=TwoWay}"/>
<DataGridTextColumn Header="Value" Binding="{Binding SignalValue, Mode=TwoWay}" />
</DataGrid.Columns>
</DataGrid>
O/P