Когда разрешается x:Reference в WPF и почему порядок элементов XAML влияет на это?
x: ссылка не может быть разрешена после перестановки элементов в XAML.
Здесь я представляю рабочий код. Просто переместите элемент DataGrid, чтобы он находился после элемента button, и привязки для MenuItem в ContextMenu и MultiBinding в Button.IsEnabled прерываются. В 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();
}
}
}
3 ответа
Я предполагаю, что это потому, что ваши ресурсы (Window.Resources) будут созданы в первую очередь, до того, как существует ссылочный экземпляр. Я хотел бы попытаться решить эту проблему через DataContext (ViewModel).
<Window.DataContext>
<yourNameSpace:YourViewModel x:Name="VieModName" />
</Window.DataContext>
<MenuItem Header="HeadrTxt" Command="{Binding CommandInViewModelCmd}" DataContext="{x:Reference Name=VieModName}" />
Взято из MSDN ( http://msdn.microsoft.com/en-us/library/ee795380.aspx).
x: Ссылка - это конструкция, определенная в XAML 2009. В WPF вы можете использовать функции XAML 2009, но только для XAML, который не скомпилирован с разметкой WPF. Скомпилированный с разметкой XAML и форма XAML BAML в настоящее время не поддерживают ключевые слова и функции языка XAML 2009.
x:Reference
следует избегать в WPF. Потому что это расширение разметки является недавним дополнением к языку XAML (2009). И это не полностью поддерживается в WPF. использование ElementName
в вашем Binding
вместо x:Reference
,
<Binding Path="SelectedItem"
ElementName="dataGridElement"/>
На MSDN.