c# - El enlace UWP en Style Setter no funciona
xaml win-universal-app (2)
Como se señaló en la sección Notas de migración en la página de propiedades Setter.Value en MSDN, UWP / Windows Runtime no admite enlaces en Style Setters.
Windows Presentation Foundation (WPF) y Microsoft Silverlight admitieron la capacidad de usar una expresión Binding para proporcionar el valor para un Setter en un estilo. Windows Runtime no admite el uso de Binding para Setter.Value (el Binding no evaluará y el Setter no tendrá ningún efecto, no obtendrá errores, pero tampoco obtendrá el resultado deseado). Cuando convierta estilos XAML de WPF o Silverlight XAML, reemplace cualquier uso de expresión de Binding con cadenas u objetos que establezcan valores, o refactorice los valores como valores de extensión de marcado {StaticResource} compartidos en lugar de los valores obtenidos de Binding.
Una solución alternativa podría ser una clase auxiliar con propiedades adjuntas para las rutas de origen de los enlaces. Crea los enlaces en el código subyacente en un PropertyChangedCallback de la propiedad auxiliar:
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) });
}
}
}
Los usarías en XAML así:
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="local:BindingHelper.GridColumnBindingPath" Value="Level"/>
<Setter Property="local:BindingHelper.GridRowBindingPath" Value="Row"/>
</Style>
</ItemsControl.ItemContainerStyle>
Para una solución simple para el posicionamiento absoluto (es decir, vincular las propiedades
Canvas.Left
y
canvas.Top
), consulte
esta respuesta
.
Tengo un problema con la creación de control xaml. Estoy escribiendo un nuevo proyecto en VS 2015 en la aplicación universal. Quiero crear cuadrícula. En esta cuadrícula quiero tener un botón. En el modelo especifico la columna (Nivel) y la Fila. Este es mi código:
<ItemsControl Grid.Row="1" ItemsSource="{Binding Path=TechnologyList}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="10*"/>
<RowDefinition Height="10*"/>
<RowDefinition Height="10*"/>
<RowDefinition Height="10*"/>
<RowDefinition Height="10*"/>
<RowDefinition Height="10*"/>
<RowDefinition Height="10*"/>
<RowDefinition Height="10*"/>
<RowDefinition Height="10*"/>
<RowDefinition Height="10*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="14*"/>
<ColumnDefinition Width="14*"/>
<ColumnDefinition Width="14*"/>
<ColumnDefinition Width="14*"/>
<ColumnDefinition Width="14*"/>
<ColumnDefinition Width="14*"/>
<ColumnDefinition Width="14*"/>
</Grid.ColumnDefinitions>
</Grid>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="Control">
<Setter Property="Grid.Column" Value="{Binding Level}" />
<Setter Property="Grid.Row" Value="{Binding Row}" />
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content="{Binding Name}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Recibo un error en la línea
<Setter Property="Grid.Column" Value="{Binding Level}" />
El error: Excepción de HRESULT: 0x8000FFFF (E_UNEXPECTED) estaba en el editor no en el código en ejecución.
¿Qué está mal?
En el "viejo" WPF todo estaba bien, pero en Universal App para Windows 10 tengo un error.
Alguien puede ayudarme ?
Quería agregar mi experiencia de esta idea BindingHelper de @clemens.
Es una solución ordenada, pero descubrí que al apuntar a un
ListViewItem
el enlace no accedería al modelo de vista subyacente.
Después de depurarlo, descubrí que necesitaba asegurarme de que el enlace fuera relativo al
ListViewItem
sí y a la propiedad
.Content
asociada para permitir que se vincule correctamente al modelo de vista del elemento.
Mi caso de uso particular fue establecer la propiedad
IsTabStop
de
ListViewItem
función de un valor de modelo de vista:
private static void BindingPathPropertyChanged(DependencyObject obj,
DependencyPropertyChangedEventArgs e)
{
if (e.NewValue is string propertyPath)
{
var binding = new Binding
{
Path = new PropertyPath($"Content.{propertyPath}"),
Mode = BindingMode.OneWay,
RelativeSource = new RelativeSource
{
Mode = RelativeSourceMode.Self
}
};
BindingOperations.SetBinding(obj, Control.IsTabStopProperty, binding);
}
}
Espero que esto ayude si alguien más tiene el problema.