I had an colleague ask me how to create a column of buttons in a XamDataGrid. He had been trying for a while and hadn't got anywhere. I told him he had to use a TemplateField, but then I realized how different the bindings for a TemplateField are, so I thought it would be a good idea to write this blog entry.
We will be looking at how to create and bind a TemplateField, specifically one containing a button.
Start a new Visual Studio WPF project using C# and .Net Core. I used .Net Core 7. Call it ButtonField. Add references to InfragisticsWPF4, Editors, and DataPresenter. Your version numbers may be different.
We will start by writing an app to display a list of employee names and salaries. Replace MainWindow XAML and code behind with this.
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:igDP="http://infragistics.com/DataPresenter"
xmlns:igEd="http://infragistics.com/Editors"
xmlns:local="clr-namespace:ButtonField"
mc:Ignorable="d"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Title="Button Field" Height="450" Width="800">
<igDP:XamDataGrid DataSource="{Binding Employees}" GroupByAreaLocation="None">
<igDP:XamDataGrid.FieldSettings>
<igDP:FieldSettings AllowEdit="False"/>
</igDP:XamDataGrid.FieldSettings>
<igDP:XamDataGrid.FieldLayoutSettings>
<igDP:FieldLayoutSettings AutoGenerateFields="False"/>
</igDP:XamDataGrid.FieldLayoutSettings>
<igDP:XamDataGrid.FieldLayouts>
<igDP:FieldLayout>
<igDP:FieldLayout.Fields>
<igDP:TextField Label="Name" Name="Name"/>
<igDP:CurrencyField Label="Salary" Name="Salary"/>
</igDP:FieldLayout.Fields>
</igDP:FieldLayout>
</igDP:XamDataGrid.FieldLayouts>
</igDP:XamDataGrid>
</Window>
------------------------------------------------------------------------------------------------------------
namespace ButtonField
[ObservableObject]
{
[ObservableProperty] public string _name;
public cEmployee(string name, decimal salary)
this.Name = name;
}
public partial class MainWindow : Window
{
public List<cEmployee> Employees { get; set; } = new List<cEmployee>()
new cEmployee("john smith", 100000),
public MainWindow()
InitializeComponent();
}
}
}
If you run this you will see a very simple grid.
Now we will add a button on each row that gives the employee a 10% salary raise. As we are adding a button we will need a command for that button.
<RoutedCommand x:Key="GiveRaiseCommand"/>
</Window.Resources>
<Window.CommandBindings>
<CommandBinding Command="{StaticResource GiveRaiseCommand}" Executed="GiveRaise_Executed"/>
</Window.CommandBindings>
Add a the GiveRaise_Executed method to the code behind.
using System.Windows.Input;
}
Add the basic TemplateField to the XAML after the name field.
<igDP:TemplateField.DisplayTemplate>
<DataTemplate>
<Button Content="Give Raise Command="{StaticResource GiveRaiseCommand}"/>
</DataTemplate>
</igDP:TemplateField.DisplayTemplate>
</igDP:TemplateField>
Now we have a button but it doesn't do much.
Let's have the content of the button tell us how much each user's raise will be. It will be different for each user and normally we would use a CellBinding to achieve this but you can't use CellBindings on TemplateFields.
We have bound the TemplateField to the employee's salary. We can add a converter to calculate 10% of the salary and bind the button's content to that. We can also specify a ContentStringFormat on the button to add the words "Give Raise". Change the TemplateField to look like this.
<igDP:TemplateField.DisplayTemplate>
<DataTemplate>
<Button Content="{igEd:TemplateEditorValueBinding}" ContentStringFormat="Give Raise {0:C}" Command="{StaticResource GiveRaiseCommand}"/>
</DataTemplate>
</igDP:TemplateField.DisplayTemplate>
</igDP:TemplateField>
To create the converter, add a class called Converters. It will look like this.
namespace ButtonField
internal class TenPercentConverter : IValueConverter
{
public object Convert(Object value, Type targetType, object parameter, CultureInfo culture)
try
{
return decimal.Parse(value.ToString()) / 10;
catch { return 0; }
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
throw new NotImplementedException();
}
}
Add a reference to the converter in the Windows.Resources section.
<local:TenPercentConverter x:Key="TenPercentConverter"/>
<RoutedCommand x:Key="GiveRaiseCommand"/>
</Window.Resources>
XamDataGrid xdg = (XamDataGrid)e.Source;
}
Run the application now and click the first button. The Salary is updated in the salary column and also in the button.
No comments:
Post a Comment