【问题标题】:Trouble Binding CommandParameter using XPath within HierarchicalDataTemplate在 HierarchicalDataTemplate 中使用 XPath 绑定 CommandParameter 时遇到问题
【发布时间】:2011-07-20 17:10:14
【问题描述】:

我对 WPF 比较陌生,遇到了一个小问题。使用 HierarchicalDataTemplates,我成功地将 XML 绑定到 TreeView 控件。每个节点都正确渲染(包括 SubstepTemplate 中的 Label)。

我什至可以从 SubstepTemplate 中的 Button 获取 ViewModel 中的绑定命令,但前提是我为 CommandParameter 输入硬编码值(例如 999)。在我的 XML 中绑定到 commandID 属性的所有尝试都失败了。

这是我现在拥有的:

XML:

<root xmlns="">
  <step label="Step Label 1">
    <button label="Button Title 1A" commandID="701" />
    <button label="Button Title 1B" commandID="702" />
    <button label="Button Title 1C" commandID="703" />
  </step>
  <step label="Step Label 2">
    <button label="Button Title 2A" commandID="801" />
    <button label="Button Title 2B" commandID="802" />
  </step>
</root>

XAML:

<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SidePanel">

<HierarchicalDataTemplate
            x:Key="SubstepTemplate"
            DataType="button"
            ItemsSource="{Binding XPath=*}">
    <StackPanel Orientation="Horizontal">
        <Button Margin="2" Width="32" Height="32" Command="{Binding ElementName=MyTreeView, Path=DataContext.PluginCommand}" CommandParameter="{Binding XPath=@commandID}" />
        <Label VerticalAlignment="Center" Margin="8,0,0,0" Content="{Binding XPath=@label}" />
    </StackPanel>
</HierarchicalDataTemplate>

<HierarchicalDataTemplate
            x:Key="StepTemplate"
            DataType="step"
            ItemsSource="{Binding XPath=*}"
            ItemTemplate="{StaticResource SubstepTemplate}">
    <Expander Header="{Binding Mode=OneWay, XPath=@label}" HorizontalAlignment="Stretch">
    </Expander>
</HierarchicalDataTemplate>

<Style TargetType="{x:Type local:SidePanelControl}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:SidePanelControl}">
                <TreeView
                    Name="MyTreeView"
                    ItemsSource="{Binding XmlRoot}"
                    ItemTemplate="{StaticResource StepTemplate}"
                    Background="{TemplateBinding Background}"
                    BorderBrush="{TemplateBinding BorderBrush}"
                    BorderThickness="{TemplateBinding BorderThickness}"
                    HorizontalAlignment="Stretch">
                </TreeView>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
</ResourceDictionary>

ViewModel 代码段:

    public DelegateCommand<string> PluginCommand
    {
        get
        {
            if (pluginCommand == null)
            {
                pluginCommand = new DelegateCommand<string>(ExecPluginCommand, canExecPluginCommand);
            }
            return pluginCommand;
        }
    }

    public void ExecPluginCommand(string param)
    {
        LogMessage("In ExecPluginCommand, param = " + param);
    }

    public bool canExecPluginCommand(string param)
    {
        return true;
    }

什么是正确的绑定表达式,需要进入 CommandParameter 以使其工作? {Binding XPath=@commandID} 似乎不起作用,我不明白为什么。

【问题讨论】:

  • 如果除了“似乎不起作用”之外,您还指定了预期和实际行为,这可能会有所帮助。
  • 如果我指定 CommandParameter="999" 我的 VM 中的 DelegateCommand 会在我单击按钮时触发。但我想要的是 XML 中的 commandID 值——我尝试过的每个 Binding 语句都会导致 DelegateCommand 永远不会被触发。

标签: wpf data-binding xpath treeview hierarchicaldatatemplate


【解决方案1】:

我发现了问题。当 XPath 用作 CommandParameter 绑定时,模板化的 DelegateCommand 接收 System.Xml.XmlNode 类型的参数,而不是字符串。

尝试获取命令数据类型时,我的命令出现异常

    void ICommand.Execute(object parameter)
    {
        TParam value = GetCommandDataType(parameter);
        Execute(value);
    }

因为 TypeConverter::CanConvertFrom 不知道如何处理 System.Xml.XmlNode 类型的参数。

我能够通过显式测试获得 commandID 值

    data is System.Xml.XmlNode

在GetCommandDataType(object data)中,然后返回.Value成员,即

        else if (data is System.Xml.XmlNode)
        {
            System.Xml.XmlNode foo = (System.Xml.XmlNode)data;
            string fooVal = foo.Value;
            TypeConverter converter = TypeDescriptor.GetConverter(typeof(string));
            result = (TParam)converter.ConvertFrom(fooVal);
        }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-09-02
    • 1970-01-01
    • 2017-01-12
    • 2015-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多