MVVM Light DataGrid binding - wpf

I'm developing a WPF with C#, .NET Framework 4.5.1, MVVM Light framework and Entity Framework 6.1.3.
I have this DataGrid in a window:
<DataGrid x:Name="LevelConfigurationDataGrid" Grid.Column="1" Grid.Row="1" Margin="20,0" ItemsSource="{Binding LevelConfigs}">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding CODE_LEVE}" Header="Nivel"/>
<DataGridTextColumn Binding="{Binding CODE_NAME}" Header="Nombre"/>
<DataGridTextColumn Binding="{Binding IS_ACTIVE}" Header="¿Activa?"/>
<DataGridTextColumn Binding="{Binding CODE_TYPE}" Header="Tipo de código"/>
<DataGridTextColumn Binding="{Binding CODE_SOURCE}" Header="Origen del código"/>
<DataGridTextColumn Binding="{Binding HELPER_CODE_TYPE}" Header="Tipo de Helper Code"/>
<DataGridTextColumn Binding="{Binding HELPER_CODE_SOURCE}" Header="Origen del helper code"/>
<DataGridTextColumn Binding="{Binding QUANTITY}" Header="Cantidad"/>
<DataGridTextColumn Binding="{Binding REMAINING_CODES}" Header="Restantes"/>
<DataGridTextColumn Binding="{Binding TRZ_ENDPOINT}" Header="TRZ IP"/>
<DataGridTextColumn Binding="{Binding TRZ_ENDPORT}" Header="TRZ Puerto"/>
</DataGrid.Columns>
</DataGrid>
And on MainViewModel:
public ObservableCollection<CODE_LEVEL_CONFIGURATION> LevelConfigs
{
get { return m_LevelConfigs; }
set
{
m_LevelConfigs = value;
RaisePropertyChanged("LevelConfigs");
}
}
And on CODE_LEVEL_CONFIGURATION:
public class CODE_LEVEL_CONFIGURATION
{
public byte CODE_LEVEL { get; set; }
public string LEVEL_NAME { get; set; }
public bool IS_ACTIVE { get; set; }
public byte CODE_TYPE { get; set; }
public byte CODE_SOURCE { get; set; }
public byte? HELPER_CODE_TYPE { get; set; }
public byte? HELPER_CODE_SOURCE { get; set; }
public int QUANTITY { get; set; }
public int REMAINING_CODES { get; set; }
public string TRZ_ENDPOINT { get; set; }
public int? TRZ_ENDPORT { get; set; }
public virtual ICollection<CODES> Codes { get; set; }
public virtual ICollection<HELPER_CODES> HelperCodes { get; set; }
}
But, when I load the data on DataGrid I get more columns that I have defined on XAML. I get my columns and 13 columns more (on for each CODE_LEVEL_CONFIGURATION property).
What am I doing wrong?

Try setting AutoGenerateColumns to False
<DataGrid x:Name="LevelConfigurationDataGrid" AutoGenerateColumns="False"
Grid.Column="1" Grid.Row="1" Margin="20,0" ItemsSource="{Binding LevelConfigs}">
<DataGrid.Columns>
...
</DataGrid.Columns>
</DataGrid>

Related

Binding ObservableCollection to DataGrid

How do I bind a ObservableCollection<updateData> updateCollection to a DataGrid? I tried several solution but none seem to work as rows are added to the collection but don't show up on the grid. I tried to bind to the class only, then I can add rows but when I try to edit them i get the error 'EditItem' is not allowed for this view. The grid is the following
<DataGrid Name="dgv" Grid.ColumnSpan="7" AutoGenerateColumns="False" ItemsSource="{Binding updateCollection}" IsSynchronizedWithCurrentItem="True" CanUserAddRows="False">
<DataGrid.Columns>
<DataGridComboBoxColumn Header="Hour" SelectedValueBinding="{Binding Active}" ItemsSource="{StaticResource hoursList}" DisplayMemberPath="Key" SelectedValuePath="Value"/>
<DataGridComboBoxColumn Header="Origin" SelectedValueBinding="{Binding Origin}" ItemsSource="{StaticResource originList}" DisplayMemberPath="Key" SelectedValuePath="Value"/>
<DataGridTextColumn Header="P" Binding="{Binding Path=Price}"/>
<DataGridTextColumn Header="Q" Binding="{Binding Path=Quantity}"/>
</DataGrid.Columns>
And the updateData class is the following:
public class updateData
{
public string Price { get; set; }
public string Quantity { get; set; }
public string Origin { get; set; }
public string Hour { get; set; }
}
What you did looks correct, but if you miss one single thing, the DataContext… nothing will work.
Here an example just for you:
This is your Model:
public class updateData
{
public string Price { get; set; }
public string Quantity { get; set; }
public string Origin { get; set; }
public string Hour { get; set; }
}
Note that, if you want to tell to your view that something has changed, you have to implement the INotifyPropertyChanged interface.
This is your ViewModel:
public class updateDataVm
{
public ObservableCollection<updateData> updateCollection { get; set; }
public updateDataVm()
{
updateCollection = new ObservableCollection<updateData>();
}
}
And finally here is your View (note that i have changed ItemsSource to ItemsSource="{Binding}"):
<Grid>
<DataGrid Name="dgv" Grid.ColumnSpan="7" AutoGenerateColumns="False" ItemsSource="{Binding}" IsSynchronizedWithCurrentItem="True" CanUserAddRows="False">
<DataGrid.Columns>
<DataGridComboBoxColumn Header="Hour" SelectedValueBinding="{Binding Active}" ItemsSource="{StaticResource hoursList}" DisplayMemberPath="Key" SelectedValuePath="Value"/>
<DataGridComboBoxColumn Header="Origin" SelectedValueBinding="{Binding Origin}" ItemsSource="{StaticResource originList}" DisplayMemberPath="Key" SelectedValuePath="Value"/>
<DataGridTextColumn Header="P" Binding="{Binding Path=Price}"/>
<DataGridTextColumn Header="Q" Binding="{Binding Path=Quantity}"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
In your window (or generally control):
public partial class MainWindow : Window
{
public updateDataVm collection;
public MainWindow()
{
InitializeComponent();
collection = new updateDataVm();
DataContext = collection;
}
}

WPF Combobox Binding Entity Framework

This is the class that the Entity Framework created from the Database.
namespace QuickTest
{
using System;
using System.Collections.Generic;
public partial class laender
{
public int idLaender { get; set; }
public string EU { get; set; }
public string FIBUPrefixKunde { get; set; }
public string FIBUPrefixLieferant { get; set; }
public string ISO2 { get; set; }
public string ISO3 { get; set; }
public string Land_DE { get; set; }
public string Land_EN { get; set; }
public Nullable<int> Vorwahl { get; set; }
public string KFZ { get; set; }
public string TLD { get; set; }
public Nullable<double> NeukundenLimitABC { get; set; }
}
}
And I simply want to show those values in a Datagrid (thats working)
But I want the EU property to be a combobox with just 2 simple options "Yes" and "No"
So there is no foreign Key to some other Table or something. When I am binding the SelectedItem to EU it just shows nothing and I dont know why
Here is the XAML of the DataGrid
<DataGrid x:Name="laenderDataGrid" AutoGenerateColumns="False" EnableRowVirtualization="True" ItemsSource="{Binding}" Margin="58,48,59,72" RowDetailsVisibilityMode="VisibleWhenSelected">
<DataGrid.Columns>
<DataGridTemplateColumn x:Name="eUColumn" Header="EU" Width="SizeToHeader">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox SelectedItem="{Binding EU}">
<ComboBoxItem Content="YES"/>
<ComboBoxItem Content="NO"/>
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn x:Name="fIBUPrefixKundeColumn" Binding="{Binding FIBUPrefixKunde}" Header="FIBUPrefix Kunde" Width="SizeToHeader"/>
<DataGridTextColumn x:Name="fIBUPrefixLieferantColumn" Binding="{Binding FIBUPrefixLieferant}" Header="FIBUPrefix Lieferant" Width="SizeToHeader"/>
<DataGridTextColumn x:Name="idLaenderColumn" Binding="{Binding idLaender}" Header="id Laender" Width="SizeToHeader"/>
<DataGridTextColumn x:Name="iSO2Column" Binding="{Binding ISO2}" Header="ISO 2" Width="SizeToHeader"/>
<DataGridTextColumn x:Name="iSO3Column" Binding="{Binding ISO3}" Header="ISO 3" Width="SizeToHeader"/>
<DataGridTextColumn x:Name="kFZColumn" Binding="{Binding KFZ}" Header="KFZ" Width="SizeToHeader"/>
<DataGridTextColumn x:Name="land_DEColumn" Binding="{Binding Land_DE}" Header="Land DE" Width="SizeToHeader"/>
<DataGridTextColumn x:Name="land_ENColumn" Binding="{Binding Land_EN}" Header="Land EN" Width="SizeToHeader"/>
<DataGridTextColumn x:Name="neukundenLimitABCColumn" Binding="{Binding NeukundenLimitABC}" Header="Neukunden Limit ABC" Width="SizeToHeader"/>
<DataGridTextColumn x:Name="tLDColumn" Binding="{Binding TLD}" Header="TLD" Width="SizeToHeader"/>
<DataGridTextColumn x:Name="vorwahlColumn" Binding="{Binding Vorwahl}" Header="Vorwahl" Width="SizeToHeader"/>
</DataGrid.Columns>
</DataGrid>
There is no binding error or any other error it's just not showing
EDIT
I got it to work I had to set the Binding to SelectedValue and SelectedValuePath to Content because I want the COntent of the Comboboxitem
SelectedValuePath="Content" SelectedValue="{Binding EU}

WPF DataGrid binding don't work caliburn micro

I can't understand why it does not work..
This is my class
public class Article : Screen
{
public string Code { get; set; }
public string Description{ get; set; }
public decimal Cost{ get; set; }
public decimal Price{ get; set; }
}
This is XAML code of DataGrid:
<DataGrid Height="211" HorizontalAlignment="Left"
Margin="12,31,0,0" VerticalAlignment="Top" Width="521"
AutoGenerateColumns="False" ItemsSource="{Binding List}">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Path=Code}" Header="Code" />
<DataGridTextColumn Binding="{Binding Path=Description}" Header="Description" />
<DataGridTextColumn Binding="{Binding Path=Cost}" Header="Cost" />
<DataGridTextColumn Binding="{Binding Path=Price}" Header="Price" />
</DataGrid.Columns>
</DataGrid>
<Button Content="Button" Height="39" HorizontalAlignment="Left"
Margin="223,262,0,0" VerticalAlignment="Top" Width="110"
x:Name="AllArticles"/>
And this is my viewmodel
[Export(typeof(IShell))]
public class ArtsViewModel : Screen
{
public List<Article> List = new List<Article>();
public void AllArticles()
{
Recover recover = new Recover(); //a model called Recover
List = recover.Import().Articles; //return a List of Article
NotifyOfPropertyChange("List");
}
}
WHY THE DATAGRID DON'T WORK ?
To enable the binding conventions in Caliburn.Micro, you normally use the x:Name property in your XAML. If you, instead of explicitly binding the List property to ItemsSource of your DataGrid, use the name convention like this:
<DataGrid x:Name="List" Height="211" HorizontalAlignment="Left"
Margin="12,31,0,0" VerticalAlignment="Top" Width="521"
AutoGenerateColumns="False">
I believe the subsequent bindings should work as desired.
Oh, and you also need to make List a property instead of a field:
public List<Article> List { get; private set; }
If you want to make sure that modifications to List are properly reflected in your data grid, you should also make your List property an IObservableCollection with a backing field:
private IObservableCollection<Article> _list;
public IObservableCollection<Article> List {
get { return _list; }
set {
_list = value;
NotifyOfPropertyChange(() => List);
}
}
a) Did you set the DataContext?
b) Try "Binding="{Binding Code}" (Without Path=), works fine for me.
For my UWP app I found that the x:Name convention didn't work and I need to use a bindable collection and bind directly to ItemsSource. I then used Path=PropertyName to specify the columns.
XAML:
<controls:DataGrid Grid.Row="3" Grid.Column="1" Grid.ColumnSpan="3" ItemsSource="{Binding RawCSVData}" AutoGenerateColumns="false">
<controls:DataGrid.Columns>
<controls:DataGridTextColumn Header="Time" Binding="{Binding Path=Time}"/>
<controls:DataGridTextColumn Header="Signal" Binding="{Binding Path=Signal}"/>
<controls:DataGridTextColumn Header="Response" Binding="{Binding Path=Response}"/>
</controls:DataGrid.Columns>
</controls:DataGrid>
CSVData.cs:
public class CSVData: Screen
{
public double Time { get; set; }
public double Signal { get; set; }
public double Response { get; set; }
}
ViewModel.cs snippet:
public BindableCollection<CSVData> RawCSVData { get; set; }
private void _bookeditpage_ConfirmBook(Book _book, bool _isnewone)
{
if (_isnewone)
{
Books.Add(_book);
}
else
{
//doesn't refresh datagrid
SelectedBook = _book;
//
//works fine :)
SelectedBook.BookName = _book.BookName;
SelectedBook.IsPrenum=_book.IsPrenum;
SelectedBook.Publisher=_book.Publisher;
//
}
}

WPF DataGridCheckColumn, check checkbox after selection changed

I have DataGrid like:
<DataGrid Name="paragonyDG" AutoGenerateColumns="False" CanUserAddRows="False" ItemsSource="{Binding zaznaczone}" >
<DataGrid.Columns>
**<DataGridCheckBoxColumn Header="Zaznacz" Binding="{Binding check}"></DataGridCheckBoxColumn>**
<DataGridTextColumn Header="Nazwa paragonu" Binding="{Binding nazwa}"></DataGridTextColumn>
<DataGridTextColumn Header="Wystawiony przez" Binding="{Binding osoba}"></DataGridTextColumn>
<DataGridTextColumn Header="Kwota paragonu" Binding="{Binding kwota}"></DataGridTextColumn>
<DataGridTextColumn Header="Rabat" Binding="{Binding rabat}"></DataGridTextColumn>
<DataGridTextColumn Header="Data otwarcia" Binding="{Binding dataO}"></DataGridTextColumn>
<DataGridTextColumn Header="Data zamknięcia" Binding="{Binding dataZ}"></DataGridTextColumn>
<DataGridTextColumn Header="Formy płatności" Binding="{Binding formy}"></DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
And its bind into class :
public class zaznaczone
{
public bool check { get; set; }
public int docID { get; set; }
public string nazwa { get; set; }
public string osoba { get; set; }
public decimal kwota { get; set; }
public decimal rabat { get; set; }
public string dataO { get; set; }
public string dataZ { get; set; }
public string formy { get; set; }
}
Now, in datagrid.selectionchanged i'd like to check this checkbox.
I've tried to parse selectedItem.columns[0] to checkbox, but i cannot parse datagridrow to "zaznaczone".
How can i check checkbox?
Specify SelectedItem property of DataGrid: SelectedItem="{Binding zaznaczoneItem}". After that you can modify check property of zaznaczoneItem.
Please note that your DataContext should implement INotifyPropertyChanged. I recommend you to look on MVVMLight framework

DataGrid does not refresh after deleting a Row

I am using PRISM and MEF frameworks.
I have a datagrid which displays some data and underneath it has RowDetailsTemplate which in turn has datagrid. Now if I try to delete a row from the datagrid under the RowDetailsTemplate, UI is not getting refreshed after the delete operation. in other words the row is getting deleted, but a empty space is left and the Rows underneath the present row doesn't move up.
Below is the code snippet.
<Controls1:DataGrid x:Name="dgProposals"
Grid.Row="1" ItemsSource="{Binding Items}" AutoGenerateColumns="False"
BorderThickness="0"
CanUserResizeColumns="False" RowDetailsVisibilityMode="Visible">
<Controls1:DataGrid.Columns>
<Controls1:DataGridTextColumn Binding="{Binding ProposalName}" Width="*"
CanUserSort="False" IsReadOnly="True" CanUserReorder="False" >
</Controls1:DataGridTextColumn>
<Controls1:DataGridTextColumn Binding="{Binding DisplayProposalType}"
Width="*" CanUserSort="False" IsReadOnly="True" CanUserReorder="False" >
</Controls1:DataGridTextColumn>
</Controls1:DataGrid.Columns>
<Controls1:DataGrid.RowDetailsTemplate >
<DataTemplate>
<Controls1:DataGrid x:Name="dgReports" ItemsSource="{Binding ReportList}"
AutoGenerateColumns="False" BorderThickness="0"
CanUserResizeColumns="False" HeadersVisibility="None">
<Controls1:DataGrid.Columns>
<Controls1:DataGridTextColumn Binding="{Binding Name}" Width="*"
CanUserSort="False" IsReadOnly="True" CanUserReorder="False" >
</Controls1:DataGridTextColumn>
<Controls1:DataGridTemplateColumn Width="100" CanUserSort="False"
CanUserReorder="False">
<Controls1:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
<Button VerticalAlignment="Center" Cursor="Hand"
Command="{Binding DataSource.EditReportNameCommand,
Source={StaticResource DataContextProxy}}"
CommandParameter="{Binding}" Margin="5,0">
</Button>
</StackPanel>
</DataTemplate>
</Controls1:DataGridTemplateColumn.CellTemplate>
</Controls1:DataGridTemplateColumn>
</Controls1:DataGrid.Columns>
</Controls1:DataGrid>
</DataTemplate>
</Controls1:DataGrid.RowDetailsTemplate>
BO Code snippet as follows:
public class ProposalPreview : NotificationObject
{
public string ProposalName { get; set; }
public int PartyId { get; set; }
public string PartyName { get; set; }
public string DisplayProposalType { get; set; }
private ObservableCollection<ArchievedReport> reportList = null;
public ObservableCollection<ArchievedReport> ReportList
{
get { return reportList; }
set { reportList = value; }
}
public ProposalPreview()
{
ProposalName = "";
DisplayProposalType = String.Empty;
ReportList = new ObservableCollection<ArchievedReport>();
}
}
public class ArchievedReport : NotificationObject
{
private string name;
public string Name
{
get { return name; }
set
{
name = value;
RaisePropertyChanged("Name");
}
}
public int ReportId { get; set; }
}
Here Items is ObservableCollection.
Hope I am clear with my description.
Kindly let me know if you need additional information.
Any help is greatly appreciated.
Thanks a lot for your time.
Thanks,
Maddy.
You need to rebind the datasource after you deleted the row.

Resources