我正在尝试将事件处理程序添加到通过XamlReader创建的DataGridTemplateColumn中的RadioButtons。 这是我正在使用的代码:
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);
我使用XamlReader创建TemplateColumn的原因是列中所需的RadioButton数量会有所不同,因此,我需要能够动态更改创建的RadioButtons数量。
创建列并将其添加到DataGrid没有问题,并且RadioButton正确显示。但是,似乎没有添加事件处理程序,因为检查按钮不会触发它。
作为旁注,只需在radioButtonString中添加“Checked ='rb_Checked'”就会抛出XamlParserException,因为XamlReader无法处理事件处理程序。
对此的任何帮助将不胜感激。
答案 0 :(得分:1)
这里的主要问题是你将事件处理程序连接到错误的RadioButton实例。应用CellTemplate时,WPF运行时将创建一个新的,因此调用LoadContent()方法在这里毫无意义。
不幸的是,当调用GenerateElement方法时,DataGridColumn类不会引发任何事件,因此您必须创建自己的自定义DataGridColumn,以便在实际应用模板后能够获得对StackPanel的引用。在此之前,没有StackPanel和RadioButton。顾名思义,DataTemplate只是模板,最终 。
如果您对使用应用于所有RadioButton的隐式Style不满意,可以执行以下操作。
创建一个继承自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 });
}
}
}
稍微修改您的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);
}
请注意,您必须更改&#34; assembly = WpfApplication2&#34;到您定义MyDataGridTemplateColumn类的程序集的名称。这同样适用于命名空间。
答案 1 :(得分:0)
您可以将EventSetter
添加到您的窗口,如下所示:
<Window.Resources>
<Style TargetType="{x:Type RadioButton}">
<EventSetter Event="Checked" Handler="RadioButton_Checked"/>
</Style>
</Window.Resources>
事件处理程序方法:
void RadioButton_Checked(object sender, RoutedEventArgs e)
{
// Handle the event...
}
这将为RadioButton
中的每个DataGrid
调用处理程序。
答案 2 :(得分:0)
如果我没记错的话,可以在XAML中添加Checked =“CheckHandlerFunction”。这可能有用。
这可能不适用于您的情况,但您是否查看了模板和绑定控件到DataContext?您可以使用它们在WPF中自动执行大量控件创建。