C# 如何以编程方式将事件处理程序添加到使用XamlReader动态创建的DataGridTemplateColumn中的单选按钮?
我正在尝试向DataGridTemplateColumn中的单选按钮添加事件处理程序,该列是通过XamlReader创建的。 以下是我正在使用的代码:C# 如何以编程方式将事件处理程序添加到使用XamlReader动态创建的DataGridTemplateColumn中的单选按钮?,c#,wpf,C#,Wpf,我正在尝试向DataGridTemplateColumn中的单选按钮添加事件处理程序,该列是通过XamlReader创建的。 以下是我正在使用的代码: string templateColumnStart = @"<DataGridTemplateColumn Header='Svar' Width='200' x:Name='myTemplateColumn' xmlns ='http://schemas.microsoft.com/winfx/2006/xaml/present
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的原因是该列中所需的单选按钮的数量会有所不同,因此,我需要能够动态更改所创建的单选按钮的数量
创建列并将其添加到DataGrid时没有问题,并且RadioButton显示正确。但是,似乎没有添加事件处理程序,因为检查按钮不会触发它
作为旁注,简单地将Checked='rb_Checked'添加到radioButtonString会引发XamlParserException,因为XamlReader无法处理事件处理程序
如果您有任何帮助,我们将不胜感激。您可以将EventSetter添加到您的窗口,如下所示:
<Window.Resources>
<Style TargetType="{x:Type RadioButton}">
<EventSetter Event="Checked" Handler="RadioButton_Checked"/>
</Style>
</Window.Resources>
这将调用DataGrid中每个单选按钮的处理程序。如果我没记错,您可以在XAML本身中添加Checked=CheckHandlerFunction。这可能行得通
这可能不适用于您的情况,但您是否研究过模板和将控件绑定到DataContext?您可以使用它们在WPF中自动创建大量控件。这里的主要问题是您将事件处理程序连接到错误的RadioButton实例。当应用CellTemplate时,WPF运行时将创建一个新的方法,因此在这里调用LoadContent方法毫无意义 不幸的是,DataGridColumn类在调用GenerateElement方法时不会引发任何事件,因此您必须创建自己的自定义DataGridColumn,以便在实际应用模板后获得对StackPanel的引用。在此之前,没有StackPanel或RadioButton。DataTemplate顾名思义就是最终应用的模板 如果您对使用应用于所有单选按钮的隐式样式不满意,可以这样做 创建从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);
}
请注意,必须将assembly=WpfApplication2更改为定义MyDataGridTemplateColumn类的程序集的名称。名称空间也是如此。提问时,请记住,如果答案适合您,请将其标记为已接受:
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);
}