将DataContext中的XmlElement绑定到控件中

时间:2016-11-02 15:57:57

标签: c# xml wpf data-binding

我的问题是接收一个包含1个XmlElement的DataContext,并将其传递给Converter。转换器需要完整的元素,因为它可以处理多个属性。问题是它收到MS.Internal.data.xmldatacollection,它包含一个XmlElement,我无法弄清楚如何继续。

<UserControl x:Class="W3.Views.ComboView" ...>
    <ComboBox Style="{StaticResource ComboButtonStyle}" Width="auto" Height="auto"
         Text="{Binding XPath=.,
                        Converter={StaticResource valueFormattingConverter }}"                IsEditable="True" />
</UserControl>

转换器类:

[ValueConversion(typeof(XmlElement), typeof(string))]
public class ValueFormattingConverter : IValueConverter
{

public object Convert(object val, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
  if (targetType != typeof(string))
    throw new InvalidOperationException("The target must be a List<string>");
  if (val == null) return new List<string>();
  XmlElement e = null;

  if (val is string ) e = val as XmlElement;
  if (e == null) return null;

  return Information.XmlAccess.FormatXmlField(e);
}

所以在这里,val作为MS.Internal.data.xmldatacollection接收,我无法弄清楚如何处理它以获取它包含的XmlElement。

重要的上下文,它为我提供了数据:                          总                      

如果我们可以修复它,修复程序也需要在这个更复杂的环境中运行:

<ContentControl x:Class="W3.Views.SimpleControlChooser"   >
    <ContentControl.Resources>
        <DataTemplate x:Key="combo" >
            <W3V:ComboView />
        </DataTemplate>
   // skipping other templates
    </ContentControl.Resources>
    <ContentControl.Style>
        <Style TargetType="{x:Type ContentControl}">
            <Setter Property="ContentTemplate" Value="{StaticResource combo}" />

            <Style.Triggers>
                <DataTrigger Binding="{Binding XPath=@format}" Value="check">
                    <Setter Property="ContentTemplate" Value="{StaticResource check}" />
                </DataTrigger>
                <DataTrigger Binding="{Binding XPath=@format}" Value="combo">
                    <Setter Property="ContentTemplate" Value="{StaticResource combo}" />
                </DataTrigger>

        //// skipping other DataTriggers

            </Style.Triggers>
        </Style>

    </ContentControl.Style>
</ContentControl>

是的,那么指定的数据在哪里?升级:

<UserControl x:Class="W3.Views.SimpleControl" ...>
     ...
  <W3V:ControlLabel x:Name="Label"  FontSize="12"                     
                    Width="{Binding LabelWidth,
                    RelativeSource={RelativeSourceAncestorType=W3V:SimpleControl}}" />

     <W3V:SimpleControlChooser Content="{Binding}" />

老实说,我不理解Content = line。

<ItemsControl  ItemsSource="{Binding XPath=*}" Margin="0,0,0,0">
  <ItemsControl.ItemTemplate>
    <DataTemplate>

      <W3V:SimpleControl x:Name="simple"  Content="{Binding}" 
            LabelWidth="{Binding LabelWidth,
                         RelativeSource={RelativeSource AncestorType=W3V:PropertyView}}" />


    </DataTemplate>
  </ItemsControl.ItemTemplate>
</ItemsControl>

这种用法目前有效,我不想打破这个让对方工作。我愿意在Convert()方法中编写条件代码,以便在需要不同的情况下适应数据。

1 个答案:

答案 0 :(得分:0)

问题与数据绑定有关,而不是与值转换器有关。

您的数据绑定假定ComboBox.DataContext 引用的对象是 XmlElement实例。但事实并非如此,因为您说数据上下文具有类型为XmlElement属性的属性。

这是事情变得有点棘手的时候。在绑定中指定PathXPath都不起作用,因为XPath is evaluated first。有效的解决方法是将组合框的数据上下文绑定到XmlElement本身:

<ComboBox
    DataContext="{Binding MyXmlElement}"
    Text="{Binding XPath=@value}" />

顺便说一下,一旦数据绑定正确,就不需要转换器来获取组合框中显示的value属性的值。

2016年11月3日编辑

如果组合框的父级的数据上下文是XmlElement个实例的数组而不是单个实例的数组,则可以始终使用索引运算符将正确的元素指向绑定:

<ComboBox
    DataContext="{Binding MyXmlElement[0]}"
    Text="{Binding XPath=@value}" />

现在,如果您仍然需要绑定到XML元素(实际上是XmlNode)而不是其中一个属性,那么您可以这样做并使用转换器:

<ComboBox
    DataContext="{Binding MyXmlElement[0]}"
    Text="{Binding XPath=., Converter={StaticResource ValueFormattingConverter}}" />

但是,您需要修复当前的转换器,因为它声明从XmlElementstring的转换,而是返回List<string>实例。

简而言之,因为在XPath之前评估了Path,所以不能在ComboBox.Text数据绑定中同时使用它们。有效的解决方法是将ComboBox.DataContext绑定到感兴趣的XmlElement,然后在XPath绑定中仅指定ComboBox.Text