wpf
Benutzerdefinierte UserControls mit Datenbindung erstellen
Suche…
Bemerkungen
Beachten Sie, dass ein UserControl sich sehr von einem Control unterscheidet. Einer der Hauptunterschiede besteht darin, dass ein UserControl eine XAML-Layoutdatei verwendet, um zu bestimmen, wo mehrere einzelne Steuerelemente platziert werden. Ein Control hingegen ist reiner Code - es gibt überhaupt keine Layoutdatei. Das Erstellen eines benutzerdefinierten Steuerelements kann in gewisser Weise effektiver sein als das Erstellen eines benutzerdefinierten UserControl.
ComboBox mit benutzerdefiniertem Standardtext
Dieses benutzerdefinierte UserControl wird als reguläre Combobox angezeigt. Im Gegensatz zum integrierten ComboBox-Objekt kann es dem Benutzer jedoch eine Standardzeichenfolge anzeigen, wenn er noch keine Auswahl getroffen hat.
Um dies zu erreichen, besteht unser UserControl aus zwei Controls. Natürlich benötigen wir eine echte ComboBox, aber wir werden auch einen normalen Label verwenden, um den Standardtext anzuzeigen.
CustomComboBox.xaml
<UserControl x:Class="UserControlDemo.CustomComboBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:cnvrt="clr-namespace:UserControlDemo"
x:Name="customComboBox">
<UserControl.Resources>
<cnvrt:InverseNullVisibilityConverter x:Key="invNullVisibleConverter" />
</UserControl.Resources>
<Grid>
<ComboBox x:Name="comboBox"
ItemsSource="{Binding ElementName=customComboBox, Path=MyItemsSource}"
SelectedItem="{Binding ElementName=customComboBox, Path=MySelectedItem}"
HorizontalContentAlignment="Left" VerticalContentAlignment="Center"/>
<Label HorizontalAlignment="Left" VerticalAlignment="Center"
Margin="0,2,20,2" IsHitTestVisible="False"
Content="{Binding ElementName=customComboBox, Path=DefaultText}"
Visibility="{Binding ElementName=comboBox, Path=SelectedItem, Converter={StaticResource invNullVisibleConverter}}"/>
</Grid>
</UserControl>
Wie Sie sehen, besteht dieses einzelne UserControl tatsächlich aus einer Gruppe von zwei einzelnen Controls. Dies ermöglicht uns eine gewisse Flexibilität, die nicht nur in einer ComboBox verfügbar ist.
Hier sind einige wichtige Dinge zu beachten:
- Das UserControl selbst hat einen
x:Name
Satz. Dies liegt daran, dass wir an Eigenschaften binden möchten, die sich im dahinter liegenden Code befinden, was bedeutet, dass es eine Möglichkeit gibt, sich selbst zu referenzieren. - Jede Bindung der ComboBox hat den Namen des UserControl als
ElementName
. Dies ist so, dass das UserControl weiß, sich selbst zu suchen, um Bindungen zu finden. - Das Label ist nicht sichtbar. Dies gibt dem Benutzer die Illusion, dass das Label Teil der ComboBox ist. Durch Festlegen von
IsHitTestVisible=false
wir, dass der Benutzer den Mauszeiger darüber bewegt oder auf das Label klickt. Alle Eingaben werden durch die unten angegebene ComboBox geleitet. - Das Label verwendet einen
InverseNullVisibility
Konverter, um zu bestimmen, ob es sich selbstInverseNullVisibility
soll oder nicht. Den Code dafür finden Sie am Ende dieses Beispiels.
CustomComboBox.xaml.cs
public partial class CustomComboBox : UserControl
{
public CustomComboBox()
{
InitializeComponent();
}
public static DependencyProperty DefaultTextProperty =
DependencyProperty.Register("DefaultText", typeof(string), typeof(CustomComboBox));
public static DependencyProperty MyItemsSourceProperty =
DependencyProperty.Register("MyItemsSource", typeof(IEnumerable), typeof(CustomComboBox));
public static DependencyProperty SelectedItemProperty =
DependencyProperty.Register("SelectedItem", typeof(object), typeof(CustomComboBox));
public string DefaultText
{
get { return (string)GetValue(DefaultTextProperty); }
set { SetValue(DefaultTextProperty, value); }
}
public IEnumerable MyItemsSource
{
get { return (IEnumerable)GetValue(MyItemsSourceProperty); }
set { SetValue(MyItemsSourceProperty, value); }
}
public object MySelectedItem
{
get { return GetValue(MySelectedItemProperty); }
set { SetValue(MySelectedItemProperty, value); }
}
}
Im Code-behind stellen wir einfach offen, welche Eigenschaften dem Programmierer mit diesem UserControl zur Verfügung stehen sollen. Da wir keinen direkten Zugriff auf die ComboBox außerhalb dieser Klasse haben, müssen wir MyItemsSource
doppelte Eigenschaften verfügbar ItemsSource
(z. B. MyItemsSource
für die ItemsSource der ItemsSource
). Dies ist jedoch ein geringfügiger Kompromiss, wenn man bedenkt, dass wir dies jetzt ähnlich wie bei einer nativen Steuerung verwenden können.
So kann das CustomComboBox
UserControl verwendet werden:
<Window x:Class="UserControlDemo.UserControlDemo"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:cntrls="clr-namespace:UserControlDemo"
Title="UserControlDemo" Height="240" Width=200>
<Grid>
<cntrls:CustomComboBox HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="165"
MyItemsSource="{Binding Options}"
MySelectedItem="{Binding SelectedOption, Mode=TwoWay}"
DefaultText="Select an option..."/>
<Grid>
</Window>
Und das Endergebnis:
Hier ist der InverseNullVisibilityConverter, der für das Label des UserControl benötigt wird. Dies ist nur eine geringfügige Abweichung von der Version von lll :
public class InverseNullVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value == null ? Visibility.Visible : Visibility.Hidden;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}