Uwp Binding in Style Setter Not Working

UWP Binding in Style Setter not working

As noted in the section Migration notes on the Setter.Value property page on MSDN, UWP/Windows Runtime does not support bindings in Style Setters.

Windows Presentation Foundation (WPF) and Microsoft Silverlight
supported the ability to use a Binding expression to supply the Value
for a Setter in a Style. The Windows Runtime doesn't support a Binding
usage for Setter.Value (the Binding won't evaluate and the Setter has
no effect, you won't get errors, but you won't get the desired result
either). When you convert XAML styles from WPF or Silverlight XAML,
replace any Binding expression usages with strings or objects that set
values, or refactor the values as shared {StaticResource} markup
extension values rather than Binding-obtained values.

A workaround could be a helper class with attached properties for the source paths of the bindings. It creates the bindings in code behind in a PropertyChangedCallback of the helper property:

public class BindingHelper
{
public static readonly DependencyProperty GridColumnBindingPathProperty =
DependencyProperty.RegisterAttached(
"GridColumnBindingPath", typeof(string), typeof(BindingHelper),
new PropertyMetadata(null, GridBindingPathPropertyChanged));

public static readonly DependencyProperty GridRowBindingPathProperty =
DependencyProperty.RegisterAttached(
"GridRowBindingPath", typeof(string), typeof(BindingHelper),
new PropertyMetadata(null, GridBindingPathPropertyChanged));

public static string GetGridColumnBindingPath(DependencyObject obj)
{
return (string)obj.GetValue(GridColumnBindingPathProperty);
}

public static void SetGridColumnBindingPath(DependencyObject obj, string value)
{
obj.SetValue(GridColumnBindingPathProperty, value);
}

public static string GetGridRowBindingPath(DependencyObject obj)
{
return (string)obj.GetValue(GridRowBindingPathProperty);
}

public static void SetGridRowBindingPath(DependencyObject obj, string value)
{
obj.SetValue(GridRowBindingPathProperty, value);
}

private static void GridBindingPathPropertyChanged(
DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
var propertyPath = e.NewValue as string;

if (propertyPath != null)
{
var gridProperty =
e.Property == GridColumnBindingPathProperty
? Grid.ColumnProperty
: Grid.RowProperty;

BindingOperations.SetBinding(
obj,
gridProperty,
new Binding { Path = new PropertyPath(propertyPath) });
}
}
}

You would use them in XAML like this:

<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="local:BindingHelper.GridColumnBindingPath" Value="Level"/>
<Setter Property="local:BindingHelper.GridRowBindingPath" Value="Row"/>
</Style>
</ItemsControl.ItemContainerStyle>

For a simple workaround for absolute positioning (i.e. binding the Canvas.Left and canvas.Top properties), see this answer.

UWP style setter value binding not working code behind

The Value of the Setter should to be set to a (data-bound) Tooltip and not Binding:

ToolTip tt = new ToolTip();
tt.SetBinding(ContentControl.ContentProperty, new Binding
{
Path = new PropertyPath("[" + cmnIndex.ToString() + "]"),
Converter = valueConverter
});

textStyle.Setters.Add(
new Setter(
ToolTipService.ToolTipProperty,
tt));

UWP Binding in Style Setter from ItemContainerStyle not working

Try adding on the TerminView codebehind constructor

(this.Content as FrameworkElement).DataContext = this;

Then you need to implement INotifyPropertyChanged. This is if for notify from the ViewModel or CodeBehind to the view. Only call OnPropertyChanged(nameof(TerminData)) or OnPropertyChanged("TerminData")

public event PropertyChangedEventHandler PropertyChanged;

private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

After that convert your TerminView.cs properties (termindata) in a dependency property.

public static readonly DependencyProperty TerminDataProperty = DependencyProperty.Register(
"TerminData", typeof (List<TerminDate>), typeof (TerminView), new PropertyMetadata(default(List<TerminDate>), TerminDataPropertyChanged));

private static void TerminDataPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = d as TerminView;
if (control != null)
control.TerminData = // Do here the logic if you what when this propety changes.
}

public List<TerminDate> TerminData
{
get { return (List<TerminDate>) GetValue(TerminDataProperty); }
set { SetValue(TerminDataProperty, value); }
}

I suggest you to read this article from Jerry Nixon.

UWP Style X:binding of margin to a function throws a System.AccessViolationException. Any ideas why, when this works fine if set in inline xaml?

UWP Style X:binding of margin to a function throws a System.AccessViolationException. Any ideas why, when this works fine if set in inline xaml?

I'm afraid you can't use binding or x:bind in the style setter, derive from official document

Windows Presentation Foundation (WPF) and Microsoft Silverlight supported the ability to use a Binding expression to supply the Value for a Setter in a Style. The Windows Runtime doesn't support a Binding usage for Setter.Value (the Binding won't evaluate and the Setter has no effect, you won't get errors, but you won't get the desired result either). When you convert XAML styles from Windows Presentation Foundation (WPF) or Microsoft Silverlight XAML, replace any Binding expression usages with strings or objects that set values, or refactor the values as shared {StaticResource} markup extension values rather than Binding -obtained values.

For this scenario, we suggest set margin in the control directly

<TextBlock Text="Hello World" Margin="{x:Bind MarginAsFraction(0.75)}" />

Binding to the DataContext within a Style results in a 'catastrophic failure?'

Binding in Setter's Value is not supported in Windows Runtime - take a look at MSDN:

Windows Presentation Foundation (WPF) and Microsoft Silverlight supported the ability to use a Binding expression to supply the Value for a Setter in a Style. The Windows Runtime doesn't support a Binding usage for Setter.Value (the Binding won't evaluate and the Setter has no effect, you won't get errors, but you won't get the desired result either). When you convert XAML styles from WPF or Silverlight XAML, replace any Binding expression usages with strings or objects that set values, or refactor the values as shared {StaticResource} markup extension values rather than Binding-obtained values.

You may also look here at Clemens answer for a workaround.

UWP Binding Orientation of an ItemsControl

That is no support in UWP. See: Setter Class (Windows.UI.Xaml) - Windows UWP applications | Microsoft Docs

Windows Presentation Foundation (WPF) and Microsoft Silverlight supported the ability to use a Binding expression to supply the Value for a Setter in a Style. The Windows Runtime doesn't support a Binding usage for Setter.Value (the Binding won't evaluate and the Setter has no effect, you won't get errors, but you won't get the desired result either). When you convert XAML styles from Windows Presentation Foundation (WPF) or Microsoft Silverlight XAML, replace any Binding expression usages with strings or objects that set values, or refactor the values as shared {StaticResource} markup extension values rather than Binding -obtained values.

But you can use attache property to do it.

Adding the Orientation property in MainPage.

    public static readonly DependencyProperty OrientationProperty = DependencyProperty.Register(
"Orientation", typeof(Orientation), typeof(MainPage), new PropertyMetadata(default(Orientation)));

public Orientation Orientation
{
get { return (Orientation) GetValue(OrientationProperty); }
set { SetValue(OrientationProperty, value); }
}

Adding the BindingHelper and define a attache property.

    public static readonly DependencyProperty ItemsPanelOrientationProperty = DependencyProperty.RegisterAttached(
"ItemsPanelOrientation", typeof(bool), typeof(BindingHelper),
new PropertyMetadata(default(bool), ItemsPanelOrientation_OnPropertyChanged));

In the ItemsPanelOrientation_OnPropertyChanged set the bind to ItemsStackPanel.Orientation.

    private static async void ItemsPanelOrientation_OnPropertyChanged(DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
if (d is ListView listView)
{
await listView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
if (listView.ItemsPanelRoot is ItemsStackPanel stackPanel)
{
BindingOperations.SetBinding(stackPanel, ItemsStackPanel.OrientationProperty, new Binding()
{
Path = new PropertyPath("Orientation"),
Mode = BindingMode.OneWay
});
}
});
}
}

In xaml, writing the BindingHelper.ItemsPanelOrientation and the ItemsPanelTemplate.

        <ListView.Style>
<Style TargetType="ListView">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<ItemsStackPanel Orientation="{Binding Orientation, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="local:BindingHelper.ItemsPanelOrientation" Value="True"></Setter>
</Style>
</ListView.Style>

And you should set the DataContext in ListView. The DataContext is the Page that name as Page1.

<Page
x:Class="KeejemairbouLirallpurpallnasfakaw.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:KeejemairbouLirallpurpallnasfakaw"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Name="Page1"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

<Grid>
<ListView DataContext="{x:Bind Page1}">
<ListView.Style>
<Style TargetType="ListView">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<ItemsStackPanel Orientation="{Binding Orientation, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="local:BindingHelper.ItemsPanelOrientation" Value="True"></Setter>
</Style>
</ListView.Style>
<ListView.Items>
<TextBlock Text="1"></TextBlock>
<TextBlock Text="2"></TextBlock>
<TextBlock Text="3"></TextBlock>
</ListView.Items>
</ListView>
</Grid>
</Page>

Writing the code in MainPage to change the Orientation.

    public MainPage()
{
this.InitializeComponent();

Task.Run(async () =>
{
while (true)
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
() => { Orientation = Orientation.Horizontal; });

await Task.Delay(TimeSpan.FromSeconds(5));

await Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
() => { Orientation = Orientation.Vertical; });

await Task.Delay(TimeSpan.FromSeconds(5));
}
});
}

All the code in github: https://github.com/lindexi/lindexi_gd/tree/43ee46e847179b61157c5bfbbdec0382ccc97268/KeejemairbouLirallpurpallnasfakaw



Related Topics



Leave a reply



Submit