我的问题是接收一个包含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()方法中编写条件代码,以便在需要不同的情况下适应数据。
答案 0 :(得分:0)
问题与数据绑定有关,而不是与值转换器有关。
您的数据绑定假定ComboBox.DataContext
引用的对象是 XmlElement
实例。但事实并非如此,因为您说数据上下文具有类型为XmlElement
属性的属性。
这是事情变得有点棘手的时候。在绑定中指定Path
和XPath
都不起作用,因为XPath is evaluated first。有效的解决方法是将组合框的数据上下文绑定到XmlElement
本身:
<ComboBox
DataContext="{Binding MyXmlElement}"
Text="{Binding XPath=@value}" />
顺便说一下,一旦数据绑定正确,就不需要转换器来获取组合框中显示的value
属性的值。
如果组合框的父级的数据上下文是XmlElement
个实例的数组而不是单个实例的数组,则可以始终使用索引运算符将正确的元素指向绑定:
<ComboBox
DataContext="{Binding MyXmlElement[0]}"
Text="{Binding XPath=@value}" />
现在,如果您仍然需要绑定到XML元素(实际上是XmlNode
)而不是其中一个属性,那么您可以这样做并使用转换器:
<ComboBox
DataContext="{Binding MyXmlElement[0]}"
Text="{Binding XPath=., Converter={StaticResource ValueFormattingConverter}}" />
但是,您需要修复当前的转换器,因为它声明从XmlElement
到string
的转换,而是返回List<string>
实例。
简而言之,因为在XPath
之前评估了Path
,所以不能在ComboBox.Text
数据绑定中同时使用它们。有效的解决方法是将ComboBox.DataContext
绑定到感兴趣的XmlElement
,然后在XPath
绑定中仅指定ComboBox.Text
。