Wpf selecteditem not working - Linq - wpf

i have one grid binded with some data, coming from database as bellow and one edit button
<DataGrid AutoGenerateColumns="False" Name="SParts_grid" HorizontalAlignment="Center" Margin="32,101,32,0" VerticalAlignment="Top" Height="187" Width="530" >
<DataGrid.Columns>
<DataGridTextColumn Header="Part No" Binding="{Binding Path=SPartID}" />
<DataGridTextColumn Header="Part Code" Width="85" Binding="{Binding Path=SPartCode}" />
<DataGridTextColumn Header="Part Name" Width="160" Binding="{Binding Path=SPartName}" />
<DataGridTextColumn Header="Model" Width="120" Binding="{Binding Path=ModelName}" />
<DataGridTextColumn Header="Location" Binding="{Binding Path=SPartLocation}" />
<DataGridCheckBoxColumn Header="Active" Width="58" Binding="{Binding Path=SPartActive}" />
</DataGrid.Columns>
</DataGrid>
<Button x:Name="btnEdit" Content="Edit" HorizontalAlignment="Left" Margin="105,323,0,0" VerticalAlignment="Top" Width="75" Click="btnEdit_Click"/>
all data fetched from db table called TblSpareParts just one column "ModelName" is from another table called TblBikeModels
so my code is below to fetch data
window loaded function
private void Window_Loaded(object sender, RoutedEventArgs e)
{
LoadParts();
}
private void LoadParts()
{
RST_DBDataContext conn = new RST_DBDataContext();
var AllPArts = (from s in conn.TblSpareParts
join m in conn.TblBikeModels on s.ModelID equals m.ModelID
select new { s.SPartName, s.SPartCode, s.SPartLocation, s.SPartID, m.ModelName }).ToArray();
SParts_grid.ItemsSource = AllPArts;
}
it works well but now if i need the selecteditem it does not work as below
private void btnEdit_Click(object sender, RoutedEventArgs e)
{
TblSparePart SelectedSPData = SParts_grid.SelectedItem as TblSparePart;
if (SelectedSPData == null)
{
MessageBox.Show("You Must Select a Part");
}
else
{
MessageBox.Show("Selected");
}
}
but when i use this LoadParts function then selecteditem works fine but it does not show the data in ModelName column
private void LoadParts()
{
RST_DBDataContext conn = new RST_DBDataContext();
List<TblSparePart> AllPArts = (from s in conn.TblSpareParts
select s).ToList();
SParts_grid.ItemsSource = AllPArts;
}
Basically problem is in LoadParts function

When you do select new { s.SPartName, s.SPartCode, s.SPartLocation, s.SPartID, m.ModelName }, you return an anonymous type, instead of TblSparePart object.
That's why the casting SParts_grid.SelectedItem as TblSparePart; returns null.

I think you have a UI design problem. Working with joined tables in DataGrid will definitely get duplicated data, that's what you may have to avoid. A better solution is to work with two DataGrids or (ComboBox and a DataGrid) one for the models table the other one is for items related to the model.
If you are working with Entity framework, then the task is much easier. You just have to point the binding to the related model table.
Take a look at this case :
public class Item
{
public int Id {get;set;}
public string Name {get;set;}
public Model Model {get;set;}
}
public class Model
{
public int Id {get;set;}
public string Name {get;set;}
}
Here you can do the as you did secondly. By loading only Items table in your DataGrid you can add a column that points to the Model Name property. It's going to be ready to be shown due to lazy loading that EF offers.
<DataGridTextColumn Header="Model" Width="120" Binding="{Binding Path=Model.name}" />

Related

how to set the width of datatable column and how to set the color of datatable column upon some condition

IN xaml.cs file(WPF Application) I have created a DataTable with 3 columns
Wanted to set the second column's width in xaml.cs only.
Also, want to set the second columns first row background color to blue(only for the cell which is in first row and 2nd column).
Have created 3 columns as :
DataTable dt= new DataTable();
dt.Columns.Add(new DataColumn("ABC");
Similarly, have added 2 more columns.
Want to set the second columns width
I am not fairly certain, if this is what you are looking for, but it is what I would do
First: let's say you have created a basic DataTable and filled it with some values, like this:
DataTable dt = new DataTable();
dt.Columns.Add("Key", typeof(int));
dt.Columns.Add("Material", typeof(string));
dt.Columns.Add("Price per Kilo", typeof(int));
dt.Rows.Add(1, "CobbleStone", 34);
dt.Rows.Add(2, "Wooden Planks", 12);
dt.Rows.Add(3, "Iron Ingots", 56);
which looks like this in the debugger:
Second: Get some VisualElement to display your Data. I'd suggest using a DataGrid for. So go your your MainWindows.xaml and add a DataGrid to your Grid with 3 DataGridTextColumns like this:
<DataGrid>
</DataGrid>
Since we want to add custiom properties to our Columns, we have to add AutoGenerateColumns="False" to our DataGrid, if we don't the DataGrid will automatically generate its columns based on its ItemsSource. Since we won't get any autogenerated Columns now, we also have to add 3 Columns resembling the 3 columns from our DataTable:
<DataGrid AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Key" />
<DataGridTextColumn Header="Material" />
<DataGridTextColumn Header="Price per Kilo" />
</DataGrid.Columns>
</DataGrid>
Third: Next we have to set the ItemsSource of our DataGrid. Unfortunately a DataGrid can't process a DataTable, so we first have to convert our DataTable into something the DataGrid can read. Let's generate a new Class for this and call it MaterialModel, which looks like this:
using System.ComponentModel;
using System.Runtime.CompilerServices;
class Model : INotifyPropertyChanged
{
private int m_Key;
public int Key
{
get
{
return m_Key;
}
set
{
m_Key = value;
OnPropertyChanged("Key");
}
}
private string m_Name;
public string Name
{
get
{
return m_Name;
}
set
{
m_Name = value;
OnPropertyChanged("Name");
}
}
private int m_Price;
public int Price
{
get
{
return m_Price;
}
set
{
m_Price = value;
OnPropertyChanged("Price");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
It has Properties and a PropertyChangedEventHandler, which will notify your VisualElement when the Property changes.
Fourth: The DataGrid doesn't accept DataTables, but it accepts Lists and ObserableCollections. Use a List, if you don't want to ever add/change your items at runtime. I'll use an ObserableCollection, which neeeds using System.Collections.ObjectModel; to work.
Create a Property of your List and add a PropertyChangedEventHandler to MainWindow.
public partial class MainWindow : Window
{
private ObservableCollection<MaterialModel> m_MaterialList;
public ObservableCollection<MaterialModel> MaterialList
{
get
{
return m_MaterialList;
}
set
{
m_MaterialList = value;
OnPropertyChanged("MaterialList");
}
}
public MainWindow()
{
// [...]
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
The next step would be to convert your DataTable into a ObservableCollection, so iterate through your DataTable and Convert each Row to one of your Models, like this:
MaterialList = new ObservableCollection<MaterialModel>();
foreach(DataRow row in dt.Rows)
{
MaterialModel model = new MaterialModel
{
Key = int.Parse(row["Key"].ToString()),
Name = row["Material"].ToString(),
Price = int.Parse(row["Price per Kilo"].ToString()),
};
MaterialList.Add(model);
}
Fivth: Your List is filled with Models, the next step would be to tell your DataGrid how to use your List. First, bind your List to the ItemsSource auf your DataGrid, then bind each DataGridTextColumn to one of the Properties in your MaterialModel, like this:
<DataGrid AutoGenerateColumns="False" ItemsSource="{Binding MaterialList}">
<DataGrid.Columns>
<DataGridTextColumn Header="Key" Binding="{Binding Key}" />
<DataGridTextColumn Header="Material" Binding="{Binding Name}" />
<DataGridTextColumn Header="Price per Kilo" Binding="{Binding Price}" />
</DataGrid.Columns>
</DataGrid>
and you'll see the DataGrid works:
Sixth: The last step is to actually set the properties of your columns, which is pretty easy, your Requirements would look something like this:
<DataGrid AutoGenerateColumns="False" ItemsSource="{Binding MaterialList}">
<DataGrid.Columns>
<DataGridTemplateColumn Header="Key" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding Key}" Background="LightBlue"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="Material" Binding="{Binding Name}" Width="300" />
<DataGridTextColumn Header="Price per Kilo" Binding="{Binding Price}" />
</DataGrid.Columns>
</DataGrid>
I haven't found a way to create a DataGrid completely in Code behind as you wanted, but this would be cosnidered bad practice anyway. WPF is designed to use this connection between xaml und c#.
If you want to manage your column properties in c# anyways, this would be a proper way to do it:
in your MainWindow.xaml.cs:
private double m_SecondColumnWidth;
public double SecondColumnWidth
{
get
{
return m_SecondColumnWidth;
}
set
{
m_SecondColumnWidth = value;
OnPropertyChanged("SecondColumnWidth");
}
}
public MainWindow()
{
SecondColumnWidth = 300;
}
XAML:
<!-- right beneath your Grid -->
<Grid.Resources>
<local:ViewModel x:Key="viewModel" />
</Grid.Resources>
<DataGridTextColumn Header="Material" Binding="{Binding Name}" Width="{Binding Source={StaticResource viewModel}, Path=SecondColumnWidth}" />
This isn't exactly what you wanted, but I hope it helps any way.

WPF DataGridComboBoxColumn binding

im having some trouble when trying to use a DataGridComboBoxColumn to update my entity framework
I have a datagrid that I am binding to a Custom Model (FunctionPrinterLookupModel), which is basically a lookup between Printers and Functions around the building. The Functions are all static, but I would like users to be able to select which printer they use for the function.
<DataGrid Grid.Row="1" x:Name="gridLookup" AutoGenerateColumns="False" Width="500" RowEditEnding="gridLookup_RowEditEnding" Margin="20">
<DataGrid.DataContext>
<Models:Printer/>
</DataGrid.DataContext>
<DataGrid.Columns>
<DataGridTextColumn Header="Function" Width="*" IsReadOnly="True" Binding="{Binding FunctionName}"/>
<!--<DataGridTextColumn Header="Printer" Width="*" Binding="{Binding PrinterName, UpdateSourceTrigger=PropertyChanged}"/>-->
<DataGridComboBoxColumn x:Name="ddlPrinters" Header="Printer" Width="*" SelectedValueBinding="{Binding PrinterID, Mode=TwoWay}" SelectedValuePath="{Binding PrinterID, Mode=TwoWay}" DisplayMemberPath="{Binding PrinterName}"/>
</DataGrid.Columns>
</DataGrid>
private void gridPrinters_RowEditEnding(object sender, DataGridRowEditEndingEventArgs e)
{
if (e.EditAction == DataGridEditAction.Commit)
{
Printer printer = (Printer)e.Row.Item;
if (printer.PrinterID != 0)
{
Printer printerDB = context.Printers.Where(s => s.PrinterID == printer.PrinterID).Single();
printerDB.PrinterName = printer.PrinterName;
context.SaveChanges();
}
else
{
Printer newPrinter = new Printer()
{
PrinterName = printer.PrinterName
};
context.Printers.Add(newPrinter);
context.SaveChanges();
}
}
RefreshPrintersGrid();
}
I am binding the DataGridComboBoxColumn in the code behind to an EF model containing list of Printers.
When the value has been selected and we trigger the RowEditEnding function, the value of the combobox is not updated in the FunctionPrinterLookupModel model. I feel like im tying myself in knots here and havent been able to find a solution that works from my hours of googling. Can any one help straighten me out?
You would be better off binding the combobox items source to a property in your ViewModel. Then bind the selected printer and in the ViewModel take action when the property changes.
<DataGridComboBoxColumn x:Name="ddlPrinters" Header="Printer" Width="*" ItemsSource="{Binding PrinterList}" SelectedItem="{Binding SelectedPrinter, Mode=TwoWay}" SelectedValuePath="PrinterID" DisplayMemberPath="PrinterName"/>
In ViewModel
Private PrinterInfo _SelectedPrinter { get; set; }
Publuc PrinterInfo SelectedPrinter
{
get
{
return _SelectedPrinter;
}
set
{
_SelectedPrinter = value;
//save value to db or other actions
}
}

The implements bind a collection of object to DataGrid in two-ways

I am trying to implement a two-ways binding between DataGrid and Collection.
What I want is delete a item in my Collection will automatically cause the DataGrid items been removing, Is there any possibility to make it ?
What I done so far is :
The code for item of my Collection.
[XmlRoot("configitem")]
public class ConfigItem : INotifyPropertyChanged
{
private bool bDelete = false;
[XmlAttribute("name")]
public string Name { get; set; }
[XmlAttribute("value")]
public string Value { get; set; }
public bool ToBeDelete {
get
{
return bDelete;
}
set
{
bDelete = value;
OnPropertyChanged("ToBeDelete");
}
}
[XmlAttribute("description")]
public string Description { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
The XAML code is :
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.Header>
<CheckBox Content="All" x:Name="chkAll" Click="chkAll_Click" />
</DataGridTemplateColumn.Header>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox Name="chkSelect" IsChecked="{Binding ToBeDelete,
Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Margin="15 2 0 0" Click="chkSelect_Click" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Width="2*" Binding="{Binding Name}" ClipboardContentBinding="{x:Null}" Header="ConfigName"/>
<DataGridTextColumn Width="2*" Binding="{Binding Value}" ClipboardContentBinding="{x:Null}" Header="ConfigValue"/>
<DataGridTextColumn Width="6*" Binding="{Binding Description}" ClipboardContentBinding="{x:Null}" Header="Description"/>
</DataGrid.Columns>
When I clicked the check box in first column.
The PropertyChanged event will be fired. This will make the value change to the collection item.And It worked.
When I click delete button. I try to delete the specified items from the current binding collection. The collection item are deleted. But Why the grid row for them weren't removed?
public void Delete()
{
List<ConfigItem> TobeRemovedList = configs.Where(x => x.ToBeDelete.Equals(true)).ToList();
TobeRemovedList.ForEach(x => configs.Remove(x));
}
Should I need to call bind again in delete button so that the DataGrid know the collection changed?
If what I did is far away from the best practice. Please kindly tell me how. Thanks.
Yes there is. You need to use ObservableCollection<T> as opposed to List<T> because latter doesn't supports change notifications. So data binding engine will not know that your list has changed and thus it can't update the DataGrid.
Also you need to keep the ObservableCollection<T> as a field, not as a local variable creating new again and again.

EF6: SaveChanges overriding, changed entities not updating in WPF

I have an overridden SaveChanges in my EF6 DbContext, where I set some dates and users. These changes are being saved to the database ok, but I have to quit and reopen my WPF form before they're visible there.
The SaveChanges override is:
//make sure we get all the changed objects
ChangeTracker.DetectChanges();
ObjectContext ctx = ((IObjectContextAdapter) this).ObjectContext;
//get the current user name...
//TODO needs checking that this works when via service.
string userID = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
userID = userID.Substring(userID.IndexOf('\\') + 1); //remove domain
foreach (var dbEntityEntry in ctx.ObjectStateManager
.GetObjectStateEntries(EntityState.Added | EntityState.Modified)
.Where(e => e.Entity is IAuditInfo))
{
switch (dbEntityEntry.State)
{
case EntityState.Added:
((IAuditInfo) dbEntityEntry.Entity).CreatedOn = DateTime.Now;
((IAuditInfo) dbEntityEntry.Entity).CreatedBy = userID;
break;
case EntityState.Modified:
((IAuditInfo) dbEntityEntry.Entity).LastUpdatedOn = DateTime.Now;
((IAuditInfo) dbEntityEntry.Entity).LastUpdatedBy = userID;
break;
case EntityState.Deleted:
case EntityState.Detached:
case EntityState.Unchanged:
default:
break;
}
}
ctx.SaveChanges(SaveOptions.None);
return base.SaveChanges();
My WPF XAML:
<Page.Resources>
<CollectionViewSource x:Key="actionStatusesViewSource"
d:DesignSource="{d:DesignInstance my:ActionStatus, CreateList=True}" />
</Page.Resources>
<Grid DataContext="{StaticResource actionStatusesViewSource}"
Margin="5">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<DataGrid Grid.Row ="1"
AutoGenerateColumns="False"
EnableRowVirtualization="True"
ItemsSource="{Binding}"
Name="actionStatusesDataGrid"
RowDetailsVisibilityMode="VisibleWhenSelected"
VerticalAlignment="Top"
ClipboardCopyMode="IncludeHeader">
<DataGrid.Columns>
<DataGridTextColumn x:Name="idColumn"
Binding="{Binding Path=Id, Mode=TwoWay}"
Header="Id"
Width="SizeToHeader" />
<DataGridTextColumn x:Name="nameColumn"
Binding="{Binding Path=Name, Mode=TwoWay}"
Header="Name"
Width="256" />
<DataGridTemplateColumn x:Name="validFromColumn"
Header="Valid From"
Width="128">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<DatePicker SelectedDate="{Binding Path=ValidFrom, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn x:Name="validToColumn"
Header="Valid To"
Width="128">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<DatePicker SelectedDate="{Binding Path=ValidTo, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn x:Name="lastUpdatedByColumn"
Binding="{Binding Path=LastUpdatedBy, Mode=TwoWay}"
Header="Updated By"
Width="SizeToHeader" />
<DataGridTextColumn x:Name="lastUpdatedOnColumn"
Binding="{Binding Path=LastUpdatedOn, Mode=TwoWay, StringFormat=\{0:dd/MM/yyyy HH:mm\}}"
Header="Updated On"
Width="SizeToCells" />
<DataGridTextColumn x:Name="createdByColumn"
Binding="{Binding Path=CreatedBy, Mode=TwoWay}"
Header="Created By"
Width="SizeToHeader" />
<DataGridTextColumn x:Name="createdOnColumn"
Binding="{Binding Path=CreatedOn, Mode=TwoWay, StringFormat=\{0:dd/MM/yyyy HH:mm\}}"
Header="Created On"
Width="SizeToCells" />
</DataGrid.Columns>
</DataGrid>
And finally my load and save code:
private RegRiskContext context; //our model context (via the service)
private DataServiceCollection<ActionStatus> actionStatusBinding; //our bound collection
private CollectionViewSource viewSource; //the view source for the collection
private delegate void OperationResultCallback(); //delegate for the dispatcher invokes
public AdminActionStatus()
{
InitializeComponent();
}
private void Page_Loaded(object sender, RoutedEventArgs e)
{
//get the CollectionViewSource object
viewSource = ((CollectionViewSource) (this.FindResource("actionStatusesViewSource")));
try
{
UIHelper.ProgressBarRun(true);
//initialise the context
context = new RegRiskContext(new Uri(RegRiskSettings.Default.ServiceURL));
//create a query ready for the async operation
DataServiceQuery<ActionStatus> dsq = context.ActionStatuses;
try
{
dsq.BeginExecute(OnQueryCompleted, dsq);
}
catch (DataServiceClientException ex)
{
MessageBox.Show(ex.ToString());
}
/* synchronous version
* note the freeze when opening the window
var q = context.ActionStatuses.OrderBy(f => f.Id);
DataServiceCollection<ActionStatus> actionStatuses = new DataServiceCollection<ActionStatus>(q);
viewSource.Source = actionStatuses;
*/
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void OnQueryCompleted(IAsyncResult result)
{
// Get the original query object from the state cache.
DataServiceQuery<ActionStatus> query = (DataServiceQuery<ActionStatus>) result.AsyncState;
//use Dispatcher to ensure we're on the UI thread!
this.Dispatcher.BeginInvoke(new OperationResultCallback(delegate
{
try
{
//instantiate the binding collection using results of the query
actionStatusBinding = new DataServiceCollection<ActionStatus>(query.EndExecute(result));
//set the Source to the collection
viewSource.Source = actionStatusBinding;
UIHelper.ProgressBarRun(false);
}
catch (DataServiceRequestException ex)
{
MessageBox.Show(ex.ToString());
}
}), null);
}
private void saveButton_Click(object sender, RoutedEventArgs e)
{
try
{
UIHelper.ProgressBarRun(true);
context.BeginSaveChanges(OnSaveChangesCompleted, null);
}
catch (DataServiceClientException ex)
{
MessageBox.Show(ex.ToString());
}
}
private void OnSaveChangesCompleted(IAsyncResult result)
{
// Use the Dispatcher to ensure that the operation returns in the UI thread.
this.Dispatcher.BeginInvoke(new OperationResultCallback(delegate
{
try
{
// Complete the save changes operation.
context.EndSaveChanges(result);
viewSource.View.Refresh();
UIHelper.ProgressBarRun(false);
}
catch (DataServiceRequestException ex)
{
MessageBox.Show(ex.ToString());
}
}), null);
}
I don't know if its because my SaveChanges override needs to notify somehow? or if its the WPF thats wrong?
There is a WCF DataServices layer between the WPF and the EF, but that looks 'straightforward' enough, and I can't see what I could even change there.
Found a solution, not entirely sure why it fixes it though, so any expanded explanation would be gratefully received.
My WCF DataService class is simple:
public class RegRiskService : EntityFrameworkDataService<BOI.RegRisk.Model.RegRiskContext>
{
// This method is called only once to initialize service-wide policies.
public static void InitializeService(DataServiceConfiguration config)
{
// TODO: set rules to indicate which entity sets and service operations are visible, updatable, etc.
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3;
//snip access stuff
}
}
It was the protocol version, it was defaulted to v2, changing it to v3 seems to have resolved the issue. My WPF datagrid now updated with the changes made in the SaveChanges override.
Again there's a caveat for anybody with the same original issue, I've been looking at this issue for a while, so there is a chance there was something else I changed that was the actual root cause!

Bind DataGridTextColumn with calculation in MVVM

I am new in Silverlight MVVM, I am creating a project where I am binding a data in to DataGrid.
Here is my database structure:
tblAuthorizationVarification
(AuthorizationVarificationid, AuthorizationRequestid, number)
tblAuthorizationRequest (AuthorizationRequestid, name)
tblAuthorizationVarificationDetails (DetailId, AuthorizationRequestid, Amount)
I want to show Total of Amount in gridview for all authorization.
Below is my code, in ViewModel class, I'm getting tblAuthorizationRequest from tblAuthorizationVarification:
PagedCollectionView _AuthorizationVarificationList;
public PagedCollectionView AuthorizationVarificationList
{
get { return _AuthorizationVarificationList; }
set
{
_AuthorizationVarificationList = value;
OnPropertyChanged("AuthorizationVarificationList"); }
}
private void GetVarifications()
{
IsBusy = true;
LoadOperation<AuthorizationVerification> loadOp =
objContext.Load(objContext.GetCreditNotesQuery());
loadOp.Completed += (sender, e) =>
{
IEnumerable<AuthorizationVerification> op =
((LoadOperation<AuthorizationVerification>)sender).Entities;
PagedCollectionView view = new PagedCollectionView(op);
this.AuthorizationVarificationList = view;
cnt = cnt - 1;
if (cnt <= 0)
IsBusy = false;
};
}
AuthorizationVarificationList is binding in Gridview as like
<sdk:DataGrid x:Name="grdCreditNotes"
ItemsSource="{Binding Path=AuthorizationVarificationList}"
SelectedItem="{Binding Path=SelectedCreditNote, Mode=TwoWay}"
AutoGenerateColumns="False" IsReadOnly="True" Grid.Row="2"
VerticalAlignment="Stretch" Margin="0,0,0,0">
<sdk:DataGrid.Columns>
<sdk:DataGridTextColumn Header="Credit No"
Binding="{Binding Path=AuthorizationVerificationId}" Width="200"/>
<sdk:DataGridTextColumn Header="Amount"
Binding="{Binding Path=AuthorizationRequest.Amount}" MinWidth="100"
Width="*"/>
</sdk:DataGrid.Columns>
</sdk:DataGrid>
What can I do for display sum of amount of particular Authorization in this field of grid?
As I've already suggested, you can create a view model class for the collection item and populate it as it should be.
public class VerificationViewModel
{
public int AuthorizationVerificationId { get; set; }
public double Amount { get; set; }
}
Then use the LINQ-query which groups the collection and returns summarized items:
loadOp.Completed += (sender, e) =>
{
IEnumerable<AuthorizationVerification> op =
((LoadOperation<AuthorizationVerification>)sender).Entities;
var models = op.GroupBy(item => item.AuthorizationVerificationId)
.Select(g => new VerificationViewModel
{
AuthorizationVerificationId = g.Key,
Amount = g.Sum(gi => gi.Amount)
})
.ToList();
PagedCollectionView view = new PagedCollectionView(models);
// Everything else is the same
}
//Also change the type of the property which is bound to SelectedItem
public VerificationViewModel SelectedCreditNote { get; set; }
And change the binding path of the second column:
<sdk:DataGrid.Columns>
<sdk:DataGridTextColumn Header="Credit No"
Binding="{Binding Path=AuthorizationVerificationId}" Width="200"/>
<sdk:DataGridTextColumn Header="Amount"
Binding="{Binding Path=Amount}" MinWidth="100" Width="*"/>
</sdk:DataGrid.Columns>
This code should calculate the sum of the Amount for each Id. If you want some other aggregation, you can change the linq query.
If I understand correctly you are after a Summary Row? If so, please check out the following link http://leeontech.wordpress.com/2010/02/01/summary-row-in-datagrid/. You will may need to shape your Model objects behind ViewModels a little better (It is rarely good practice to show Models (DTOs in this case) directly to the View).

Resources