#c# #uwp #uwp-xaml #resourcedictionary
#c# #uwp #uwp-xaml #resourcedictionary
Вопрос:
У меня есть несколько методов, к которым я привязываю x:, чтобы установить размер элемента на основе размера основного элемента управления. Все работает хорошо, за исключением случаев привязки функции к свойству Margin в моем пользовательском элементе управления (из словаря стилей) Я получаю систему.Исключение AccessViolationException.
Я не получаю исключение при привязке к элементу напрямую — только при использовании в установщике стиля. Очевидно, можно обойти это, установив свойство в xaml для объекта, но хотелось бы знать, является ли это ошибкой или я что-то упускаю? Привязка функции из словаря работает со всеми другими свойствами, которые я использую (только не на полях). Любые советы или рекомендации будут оценены.
Фрагмент XAML:
<UserControl.Resources>
<ResourceDictionary>
<Style TargetType="Path" x:Key="Ball.Shadow">
<Setter Property="Height" Value="{x:Bind DimensionAsFraction(0.5)}" />
...
</Style>
<Style TargetType="TextBlock" x:Key="Ball.Letter" BasedOn="{StaticResource Ball.Text}">
<Setter Property="Margin" Value="{x:Bind MarginAsFraction(0.075), Mode=OneWay}" />
...
</style>
объект.Высота — это высота элемента управления хоста — она была установлена
до инициализации компонента и отлично работает при ссылках
из других установщиков кода и стиля.
Фрагмент кода:
public sealed partial class Example : UserControl
{
private void SetDefaults()
{
Height = 200;
Width = 200;
}
private int calculateAsInt(double fraction) => (int)(object.Height * fraction);
private double DimensionAsFraction(double fraction) => calculateAsInt(fraction);
private Thickness MarginAsFraction(double fraction) => new Thickness(0, calculateAsInt(fraction), 0, 0);
private Thickness BorderAsFraction(double fraction) => new Thickness(calculateAsInt(fraction));
public Example()
{
SetDefaults();
this.InitializeComponent();
}
}
Спасибо: D
Ответ №1:
UWP Стиль X: привязка поля к функции выбрасывает систему.Исключение AccessViolationException. Есть идеи, почему, когда это работает нормально, если задано во встроенном xaml?
Боюсь, вы не можете использовать привязку или x: bind в установщике стиля, производном от официального документа
Windows Presentation Foundation (WPF) и Microsoft Silverlight поддерживали возможность использования выражения привязки для указания значения для параметра установки в стиле. Среда выполнения Windows не поддерживает использование привязки для Setter.Значение (привязка не будет оцениваться, и установщик не будет иметь никакого эффекта, вы не получите ошибок, но и желаемого результата вы не получите). При преобразовании стилей XAML из Windows Presentation Foundation (WPF) или Microsoft Silverlight XAML замените любое использование выражения привязки строками или объектами, которые задают значения, или реорганизуйте значения как общие значения расширения разметки {StaticResource}, а не значения, полученные при привязке.
Для этого сценария мы предлагаем установить поле в элементе управления напрямую
<TextBlock Text="Hello World" Margin="{x:Bind MarginAsFraction(0.75)}" />
Комментарии:
1. Спасибо, Нико. Это действительно отвечает на мой вопрос. Я ценю ваше время и задаю дополнительный вопрос, если вы готовы ответить на него…. Что вы думаете о некоторых выражениях привязки, которые явно оцениваются и дают требуемый для меня эффект (например: <Свойство Setter=»Width» Value=»{x:Привязка DimensionAsFraction(0.8)}» /> <Свойство Setter=»Height» Value=»{x:Привязать размерность к фракции(0.4)}» />). Согласны ли вы с тем, что они не должны работать и на самом деле являются ошибкой, учитывая предоставленную вами информацию? Большое спасибо
2. Да, ваш x:bind явно, к сожалению, не разрешен на платформе UWP в установщике стилей. это не ошибка, это по замыслу.
3. Спасибо, Нико. Ты качаешься!
Ответ №2:
Я наткнулся на эту тему, пытаясь решить аналогичную проблему, которая привела к ошибке переполнения стека:
<Style TargetType="GridViewItem">
<Setter Property="Margin" Value="{x:Bind MyMargin, Mode=OneWay"/>
</Style>
Для моего варианта использования я не чувствовал, что установка поля элемента управления была подходящей, потому что это означало, что поле выбора (при использовании клавиатуры) было не вокруг элемента управления, а элемента управления и поля. Поскольку у меня неравномерное поле, оно выглядело неправильно.
Мое решение состояло в том, чтобы установить код позади в событии изменения размера страницы (поскольку именно тогда и именно поэтому я меняю поле).
Dim Width As Integer = SomeFunctionOf(WindowSize.Width)
Dim NewMargin As New Thickness(Width, 0, Width, 0)
Dim MarginStyle As New Style(GetType(GridViewItem))
MarginStyle.Setters.Add(New Setter(MarginProperty, NewMargin))
MyGridView.ItemContainerStyle = MarginStyle
Не оптимально, но это сработало для меня. Возможно, это поможет кому-то в будущем.
— Обновить —
После того, как я опубликовал это, я задумался об этом и понял, что могу использовать тот же код, что и выше, но вместо установки MyGridView.ItemContainerStyle в коде, я мог бы вместо этого установить свойство в моей ViewModel, например MyViewModel .MarignStyle = MarginStyle . Затем используйте привязку с:
<GridView x:Name="MyGridView" ItemsSource="{x:Bind MyViewModel.ItemsView, Mode=OneTime}" ItemContainerStyle="{x:Bind MyViewModel.MarginStyle,Mode=OneWay}">
В любом случае, обе версии работают для меня.