【问题标题】:When is x:Reference in WPF resolved and why does XAML element order affect it?何时解析 WPF 中的 x:Reference 以及为什么 XAML 元素顺序会影响它?
【发布时间】:2013-02-01 11:05:39
【问题描述】:

x:我在 XAML 中重新排列元素后无法解析引用。

在这里,我提供了一个工作代码。只需移动 DataGrid 元素,使其位于按钮元素之后,并且 ContextMenu 中的 MenuItem 和 Button.IsEnabled 中的 MultiBinding 的绑定被破坏。在 Button.IsEnabled 中,只有 MultiBinding 被破坏。它可以替换为注释块,并且 x:Reference 在该单个绑定中起作用。

两者都抛出 XamlParseException。

  • MenuItem 给出 System.Xaml.XamlObjectWriterException 和有关未解析引用的消息。
  • MultiBinding 将 System.Collections.Generic.KeyNotFoundException 作为内部异常。

那么 x:Reference 是什么时候真正解决的?为什么只有一些绑定在被引用元素出现在引用它的元素之后时会中断?

这是我的 XAML:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:xxx="clr-namespace:WpfApplication1"
        Title="MainWindow" SizeToContent="WidthAndHeight">
    <Window.Resources>
        <xxx:BoolToVisibleConverter x:Key="boolToVisibleConv"></xxx:BoolToVisibleConverter>
        <xxx:NullToFalseConverter x:Key="nullToFalseConv"></xxx:NullToFalseConverter>
        <xxx:NullsOrToFalseConverter x:Key="nullsOrToFalseConv"></xxx:NullsOrToFalseConverter>
        <ContextMenu x:Key="MyMenu">
            <MenuItem 
                Header="Menuitem enabled when row selected" 
                IsEnabled="{Binding 
                    Path=SelectedItem, 
                    Source={x:Reference dataGridElement}, 
                    Converter={StaticResource nullToFalseConv}}" />
        </ContextMenu>
    </Window.Resources>
    <StackPanel>
        <DataGrid 
            Name="dataGridElement" 
            IsReadOnly="True" />
        <Button 
            Content="Button" 
            ContextMenu="{StaticResource MyMenu}" 
            Visibility="{Binding 
                Path=IsReadOnly, 
                Source={x:Reference dataGridElement},
                Converter={StaticResource boolToVisibleConv}}">
            <Button.IsEnabled>
                <!--<Binding 
                    Path="SelectedItem" 
                    Source="{x:Reference dataGridElement}" 
                    Converter="{StaticResource nullToFalseConv}"/>-->
                <MultiBinding 
                    Converter="{StaticResource nullsOrToFalseConv}">
                    <Binding 
                        Path="SelectedItem" 
                        Source="{x:Reference dataGridElement}"/>
                    <Binding 
                        Path="SelectedItem" 
                        Source="{x:Reference dataGridElement}"/>
                </MultiBinding>
            </Button.IsEnabled>
        </Button>
    </StackPanel>
</Window>

这是我的代码背后(没有使用):

namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    }
    public class BoolToVisibleConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (value == null || (bool)value == false)
                return System.Windows.Visibility.Hidden;
            else
                return System.Windows.Visibility.Visible;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    public class NullsOrToFalseConverter : IMultiValueConverter
    {
        public object Convert(object[] value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            foreach (object val in value)
            {
                if (val == null)
                    return false;
            }
            return true;
        }

        public object[] ConvertBack(object value, Type[] targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    public class NullToFalseConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return (value != null);
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

【问题讨论】:

    标签: wpf binding reference xamlparseexception


    【解决方案1】:

    我想这是因为您的资源(Window.Resources)将在引用实例存在之前首先创建。我会尝试通过 DataContext (ViewModel) 来解决这个问题。

    <Window.DataContext>
            <yourNameSpace:YourViewModel x:Name="VieModName" />
        </Window.DataContext>
    <MenuItem Header="HeadrTxt" Command="{Binding CommandInViewModelCmd}" DataContext="{x:Reference Name=VieModName}" />
    

    【讨论】:

      【解决方案2】:

      摘自 MSDN(http://msdn.microsoft.com/en-us/library/ee795380.aspx)。

      x:Reference 是 XAML 2009 中定义的构造。在 WPF 中,您可以使用 XAML 2009 功能,但仅适用于非 WPF 标记编译的 XAML。 标记编译的 XAML 和 XAML 的 BAML 形式目前不支持 支持 XAML 2009 语言关键字和功能。

      【讨论】:

        【解决方案3】:

        x:Reference 在 WPF 中必须避免使用。因为这个标记扩展是最近添加到 XAML 语言 (2009) 的。 WPF 并不完全支持它。在您的Binding 中使用ElementName 而不是x:Reference

        <Binding Path="SelectedItem" 
                 ElementName="dataGridElement"/>
        

        开启MSDN

        【讨论】:

        • 问题是有时 ElementName 找不到元素。这就是我首先使用 x:Reference 的最初原因。据我了解,x:Reference 是 ElementName 不起作用时的一种解决方法。他们都不工作的情况呢?例如,在这种情况下,使用 ElementName 适用于 Button.IsEnabled 中的 MultiBinding,但不适用于启用上下文菜单项。
        • @user2032138 在 MSDN 文章中有解释,“但仅适用于不是 WPF 标记编译的 XAML。”
        • 那么在这种情况下,当 XAML 描述应用程序的主 UI 时,不支持使用 x:Reference?
        • @user2032138 我从未使用过它。但在大多数情况下,它并没有什么用处,可以用 ElementName 代替。
        • @Cédric Bignon,在某些特定情况下 ElementName 不起作用,而 {x:Reference} 是 .NET 4 的绝佳解决方法或以上。具体来说,尝试从 DataGridTemplateColumn 中绑定时,ElementName 由于 WPF 树中的问题而失败,尽管根据我的经验,它只影响 Windows XP。见this stackoverflow questionthis one
        猜你喜欢
        • 1970-01-01
        • 2021-03-16
        • 2015-09-05
        • 2012-05-11
        • 1970-01-01
        • 2020-11-29
        • 1970-01-01
        • 2014-11-25
        • 1970-01-01
        相关资源
        最近更新 更多