WPF: legame TwoWay tra 4 e TextBoxes 1 Border.Margin
-
29-09-2019 - |
Domanda
Voglio impostare il BorderThickness di un bordo di un UserControl con 4 caselle di testo, ma non riesco a farlo funzionare.
codice XAML che dimostra il problema (questo codice solo in combinazione con il convertitore è necessaria):
<Window
x:Class="BorderThicknessBindingTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:BorderThicknessBindingTest="clr-namespace:BorderThicknessBindingTest"
Height="300" Width="500">
<Window.Resources>
<BorderThicknessBindingTest:ThicknessConverter x:Key="ThicknessConverter"/>
</Window.Resources>
<Grid Margin="10">
<Border
x:Name="MyBorder"
BorderBrush="Black"
Background="AliceBlue"
BorderThickness="3"/>
<TextBox
HorizontalAlignment="Center" VerticalAlignment="Center"
Text="{Binding Path=BorderThickness.Left, ElementName=MyBorder, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource ThicknessConverter}}"/>
</Grid>
</Window>
È necessario un convertitore per analizzare l'input stringa nella casella di testo:
public class ThicknessConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value; // don't need to do anything here
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
double d;
Double.TryParse((string) value, out d); // Thickness.Left doesn't take a string
return d;
}
}
Il TextBox visualizza correttamente la parte sinistra del spessore, ma la modifica della TextBox non si traduca in un cambiamento nel modo in cui il lato sinistro del bordo è reso. Stranamente, il valore che ho impostato nel controllo TextBox per Thickness.Left persiste, così sembra che il valore fa arrivare set, ma la resa non è aggiornato. Nel codice di esempio, la modifica del valore nel controllo TextBox, quindi il ridimensionamento della finestra, mostra che il bordo a sinistra fa occupano spazio aggiuntivo, ma questo spazio è vuoto.
Qualcuno sa come fare per e risoluzione di questo?
Soluzione
Non è aggiornare dinamicamente l'elemento sullo schermo perché nulla ha detto l'elemento che un campo nella sua proprietà BorderThickness
è cambiato. È necessario informare l'elemento che la sua BorderThickness
è cambiato, che si può fare solo impostando direttamente la proprietà di dipendenza a un nuovo valore -. Per esempio, rendendo l'obiettivo di un legame con un oggetto che fa la notifica delle modifiche
E 'qualcosa di un dolore per fare un modello di vista per questo, ma una volta fatto, è fatto.
La finestra:
<Window x:Class="ThicknessDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:ComponentModel="clr-namespace:System.ComponentModel;assembly=System" xmlns:ThicknessDemo="clr-namespace:ThicknessDemo" Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<ThicknessDemo:ThicknessViewModel x:Key="thickness" />
</Window.Resources>
<DockPanel DataContext="{StaticResource thickness}">
<Border DockPanel.Dock="Top"
Width="100"
Height="50"
Margin="5"
BorderBrush="Blue"
BorderThickness="{Binding Thickness}" />
<TextBox DockPanel.Dock="Top"
Text="{Binding Left, Mode=TwoWay}" />
<TextBox DockPanel.Dock="Top"
Text="{Binding Right, Mode=TwoWay}" />
<TextBox DockPanel.Dock="Top"
Text="{Binding Top, Mode=TwoWay}" />
<TextBox DockPanel.Dock="Top"
Text="{Binding Bottom, Mode=TwoWay}" />
<TextBlock DockPanel.Dock="Top" />
</DockPanel>
</Window>
Il modello di vista:
public class ThicknessViewModel : INotifyPropertyChanged
{
private void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler h = PropertyChanged;
if (h != null)
{
h(this, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
public ThicknessViewModel()
{
_Thickness = new Thickness(1, 1, 1, 1);
}
private Thickness _Thickness;
public Thickness Thickness { get { return _Thickness; } set { _Thickness = value;} }
public double Left
{
get { return _Thickness.Left; }
set
{
_Thickness.Left = value;
OnPropertyChanged("Thickness");
}
}
public double Right
{
get { return _Thickness.Right; }
set
{
_Thickness.Right = value;
OnPropertyChanged("Thickness");
}
}
public double Top
{
get { return _Thickness.Top; }
set
{
_Thickness.Top = value;
OnPropertyChanged("Thickness");
}
}
public double Bottom
{
get { return _Thickness.Bottom; }
set
{
_Thickness.Bottom = value;
OnPropertyChanged("Thickness");
}
}
}
Altri suggerimenti
Credo che questo vi punto nella giusta direzione:. Leggi metà ha 2 modi di affrontare questo, uno con un convertitore e una senza
http://10rem.net/blog/2010/05/08/breaking-apart-the-margin-property-in-xaml-for-better-binding
La soluzione più semplice per me si rivela essere a solo ascoltare l'evento TextChanged del controllo TextBox, e sostituire il BorderThickness in codice dietro.
MainWindow.xaml:
<Window
x:Class="BorderThicknessBindingTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:BorderThicknessBindingTest="clr-namespace:BorderThicknessBindingTest"
Height="300" Width="500">
<Grid Margin="10">
<Border
x:Name="MyBorder"
BorderBrush="Black"
Background="AliceBlue"
BorderThickness="3"/>
<TextBox
x:Name="MyTextBox"
HorizontalAlignment="Center" VerticalAlignment="Center"
Text="{Binding Path=BorderThickness.Left, ElementName=MyBorder, Mode=OneWay}"/>
</Grid>
</Window>
MainWindow.xaml.cs, nel costruttore:
MyTextBox.TextChanged += (sender, e) =>
{
double d;
if (!double.TryParse(MyTextBox.Text, out d)) return;
var t = MyBorder.BorderThickness;
t.Left = d;
MyBorder.BorderThickness = t;
};
In questo momento questo funziona per me, la soluzione di Robert Rossney è meglio.