将字符串用作Silverlight中的数据模板的数据模板时的事件处理程序

Kul*_*gar 7 c# silverlight xaml

我试图使用字符串以编程方式为数据形式创建一些xaml.我可以让组合框出现.但是当我尝试使用在字符串中指定"MouseLeftButtonUp"或"Loaded"事件处理程序的代码时; 进入后,页面将变为白色(没有明显的错误).请参阅下面的相关代码.

     StringBuilder editTemplate = new StringBuilder("");
     editTemplate.Append("<DataTemplate ");
     editTemplate.Append("xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' ");
     editTemplate.Append("xmlns:toolkit='http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit' ");
     editTemplate.Append("xmlns:navigation='clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation' ");
     editTemplate.Append("xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' >");
     editTemplate.Append("<StackPanel>");
     editTemplate.Append(@"  <toolkit:DataField Label='" + GetFieldWithoutNumber(theInfo, theDataContext) + "'>");
     /* Won't Work */ editTemplate.Append(@" <ComboBox MouseLeftButtonUp='ComboBox_MouseLeftButtonUp' />");
     /* Will Work  */ editTemplate.Append(@" <ComboBox />");
     editTemplate.Append(@" </toolkit:DataField>");
     editTemplate.Append("</StackPanel></DataTemplate>");
     dynamicDataForm.EditTemplate = XamlReader.Load(editTemplate.ToString()) as DataTemplate;
Run Code Online (Sandbox Code Playgroud)

Joh*_*wen 1

在 XAML 中连接的事件处理程序需要在连接到 XAML 文件的代码隐藏中声明。对于 ResourceDictionary 或从 XamlReader.Load 加载的任何内容,不能有任何代码隐藏,因此无法在 XAML 中设置事件处理程序。解决此限制的最简单方法是不从字符串构建模板,而只需在 XAML 文件的资源部分中声明它,然后您可以执行以下操作:

Resources["MyTemplate"] as DataTemplate

获取模板并在代码中分配它,就像您在此处所做的那样,或者仅在 XAML 中使用 StaticResource。只要它位于连接到此代码的同一个 XAML 文件中,当前其中的事件处理程序就应该可以正常工作。字符串的动态部分也需要更改为使用绑定。

如果您想坚持使用 XamlReader 方法,则有两个问题需要解决。

  1. 在渲染的模板中找到 ComboBox 实例
  2. 等到模板呈现后寻找 ComboBox

要找到 ComboBox,您需要首先在模板文本中为其指定 x:Name 属性(您可以替换当前存在的事件代码)。接下来,您需要能够按名称在可视化树中找到项目。这相当简单,您可以在此处找到一个示例来执行此操作。

要在正确的时间调用此代码,您要么需要重写 OnApplyTemplate(不幸的是,如果您处于 UserControl 之类的情况下,这将不起作用),要么使用另一个技巧来阻止它运行,直到渲染所有控件。这是一个完整的示例,可以放入构造函数并使用上面链接的 find 方法:

DataTemplate template = Resources["MyTemplate"] as DataTemplate;
dynamicDataForm.ContentTemplate = template;

Dispatcher.BeginInvoke(() =>
{
    ComboBox button = FindVisualChildByName<ComboBox>(this, "MyControl");
    if (button != null)
        button.MouseLeftButtonUp += (s, _) => MessageBox.Show("Click");
});
Run Code Online (Sandbox Code Playgroud)

在您的情况下,您的模板可能需要等待在渲染之前切换到编辑状态,在这种情况下,您需要推迟连接事件,并在数据表单上找到该状态更改时发生的其他事件。