[英]How do I programmatically add event handlers to RadioButtons in a DataGridTemplateColumn that is dynamically created using XamlReader?
I am trying to add event handlers to RadioButtons in a DataGridTemplateColumn which is created through XamlReader. 我试图将事件处理程序添加到通过XamlReader创建的DataGridTemplateColumn中的RadioButtons中。 Here is the code I'm using:
这是我正在使用的代码:
string templateColumnStart = @"<DataGridTemplateColumn Header='Svar' Width='200' x:Name='myTemplateColumn'
xmlns ='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation='Horizontal'>";
string templateColumnEnd = @"</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>";
string radioButtonString = @"<RadioButton Name='rb1' Content='1' IsChecked='false'/>";
string fullXamlString = templateColumnStart + radioButtonString + templateColumnEnd;
MemoryStream stream = new MemoryStream(ASCIIEncoding.UTF8.GetBytes(fullXamlString));
DataGridTemplateColumn templateColumn = (DataGridTemplateColumn)XamlReader.Load(stream);
StackPanel template = (StackPanel)templateColumn.CellTemplate.LoadContent();
RadioButton radiobutton = (RadioButton)template.FindName("rb1");
radiobutton.Checked += new RoutedEventHandler(rb_Checked);
myDataGrid.Columns.Add(templateColumn);
The reason I'm using XamlReader to create the TemplateColumn is that the number of RadioButtons needed in the column will vary, and as such, I need the ability to dynamically change the number of RadioButtons created. 我使用XamlReader创建TemplateColumn的原因是,该列中所需的RadioButtons数量会有所不同,因此,我需要能够动态更改创建的RadioButtons的数量。
The column is created and added to the DataGrid without a problem, and the RadioButton is displayed correctly. 创建该列并将其毫无问题地添加到DataGrid,并且RadioButton可以正确显示。 However, the event handler does not seem to have been added, as checking the button does not trigger it.
但是,似乎未添加事件处理程序,因为检查按钮不会触发它。
As a side note, simply adding "Checked='rb_Checked'" to the radioButtonString throws a XamlParserException, as XamlReader is not able to handle event handlers. 附带说明一下,仅将“ Checked ='rb_Checked'”添加到radioButtonString会引发XamlParserException,因为XamlReader无法处理事件处理程序。
Any help with this would be greatly appreciated. 任何帮助,将不胜感激。
The main issue here is that you are hooking up the event handler to the wrong RadioButton instance. 这里的主要问题是您将事件处理程序连接到错误的RadioButton实例。 A new one will be created by the WPF runtime when the CellTemplate is applied so calling the LoadContent() method is meaningless here.
当应用CellTemplate时,WPF运行时将创建一个新对象,因此在这里调用LoadContent()方法是没有意义的。
Unfortunately the DataGridColumn class doesn't raise any events when the GenerateElement method is invoked so you will have to create your own custom DataGridColumn to be able to get a reference to the StackPanel once the template has actually been applied. 不幸的是,当调用GenerateElement方法时,DataGridColumn类不会引发任何事件,因此一旦模板被实际应用,您将必须创建自己的自定义DataGridColumn才能获得对StackPanel的引用。 Before this there is no StackPanel nor RadioButton.
在此之前,没有StackPanel或RadioButton。 A DataTemplate is as the name implies just a template that is being applied eventually .
顾名思义,DataTemplate只是一个最终要应用的模板 。
Here is what you could do if you are not satisfied with using an implicit Style that gets applied to all RadioButtons. 如果您不满意使用适用于所有RadioButton的隐式样式,可以执行以下操作。
Create a custom class that inherits from DataGridTemplateColumn and raises an event when the GenerateElement method is called: 创建一个自定义类,该类继承自DataGridTemplateColumn,并在调用GenerateElement方法时引发一个事件:
namespace WpfApplication2
{
public class CellElementGeneratedEventArgs : EventArgs
{
public FrameworkElement Content { get; set; }
}
public delegate void CellElementGeneratedEventHandler(object sender, CellElementGeneratedEventArgs e);
public class MyDataGridTemplateColumn : DataGridTemplateColumn
{
public event CellElementGeneratedEventHandler ElementGenerated;
protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
{
FrameworkElement fe = base.GenerateElement(cell, dataItem);
if(fe != null)
fe.Loaded += Fe_Loaded;
return fe;
}
private void Fe_Loaded(object sender, RoutedEventArgs e)
{
if (ElementGenerated != null)
ElementGenerated(this, new CellElementGeneratedEventArgs() { Content = sender as FrameworkElement });
}
}
}
And modify your XAML markup and code slightly: 并稍微修改您的XAML标记和代码:
string templateColumnStart = @"<local:MyDataGridTemplateColumn Header='Svar' Width='200' x:Name='myTemplateColumn' xmlns ='http://schemas.microsoft.com/winfx/2006/xaml/presentation' xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' xmlns:local='clr-namespace:WpfApplication2;assembly=WpfApplication2'> <DataGridTemplateColumn.CellTemplate><DataTemplate><StackPanel Orientation='Horizontal'>";
string templateColumnEnd = @"</StackPanel></DataTemplate></DataGridTemplateColumn.CellTemplate></local:MyDataGridTemplateColumn>";
string radioButtonString = @"<RadioButton Name='rb1' Content='1' IsChecked='false'/>";
string fullXamlString = templateColumnStart + radioButtonString + templateColumnEnd;
using (MemoryStream stream = new MemoryStream(ASCIIEncoding.UTF8.GetBytes(fullXamlString)))
{
MyDataGridTemplateColumn templateColumn = (MyDataGridTemplateColumn)XamlReader.Load(stream);
templateColumn.ElementGenerated += (ss, ee) =>
{
ContentPresenter cc = ee.Content as ContentPresenter;
if(cc != null)
{
StackPanel sp = VisualTreeHelper.GetChild(cc, 0) as StackPanel;
if(sp != null)
{
RadioButton rb = sp.FindName("rb1") as RadioButton;
if (rb != null)
rb.Checked += rb_Checked;
}
}
};
myDataGrid.Columns.Add(templateColumn);
}
Note that the you will have to change "assembly=WpfApplication2" to the name of the assembly where you define your MyDataGridTemplateColumn class. 请注意,您必须将“ assembly = WpfApplication2”更改为定义MyDataGridTemplateColumn类的程序集的名称。 The same applies to the namespace.
命名空间也是如此。
You can add EventSetter
to your window like this: 您可以像这样将
EventSetter
添加到窗口中:
<Window.Resources>
<Style TargetType="{x:Type RadioButton}">
<EventSetter Event="Checked" Handler="RadioButton_Checked"/>
</Style>
</Window.Resources>
Event handler method: 事件处理程序方法:
void RadioButton_Checked(object sender, RoutedEventArgs e)
{
// Handle the event...
}
This will call the handler for every RadioButton
in your DataGrid
. 这将为
DataGrid
每个RadioButton
调用处理程序。
If I remember correctly, you can add Checked="CheckHandlerFunction" in the XAML itself. 如果我没记错的话,可以在XAML本身中添加Checked =“ CheckHandlerFunction”。 That may work.
那可能行得通。
This may not apply in your situation, but have you looked into templates and binding controls to DataContext? 这可能不适用于您的情况,但是您是否研究过模板以及将控件绑定到DataContext的方法? You can automate a lot of control creation in WPF using them.
您可以使用它们在WPF中自动执行很多控件创建。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.