wpf
Skapa anpassade UserControls med databindning
Sök…
Anmärkningar
Observera att en UserControl skiljer sig mycket från en kontroll. En av de främsta skillnaderna är att en UserControl använder en XAML-layoutfil för att avgöra var flera individuella kontroller ska placeras. En kontroll, å andra sidan, är bara ren kod - det finns ingen layoutfil alls. På vissa sätt kan det vara effektivare att skapa en anpassad kontroll än att skapa en anpassad UserControl.
ComboBox med anpassad standardtext
Denna anpassade UserControl kommer att visas som en vanlig kombobox, men till skillnad från det inbyggda ComboBox-objektet kan det visa användaren en standardsträng med text om de inte har gjort något val ännu.
För att uppnå detta kommer vår UserControl att bestå av två kontroller. Vi behöver uppenbarligen en faktisk ComboBox, men vi kommer också att använda en vanlig etikett för att visa standardtexten.
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>
Som ni ser är den här enda UserControl faktiskt en grupp med två individuella kontroller. Detta tillåter oss viss flexibilitet som inte är tillgänglig i en enda ComboBox ensam.
Här är flera viktiga saker att notera:
- UserControl själv har en
x:Name
inställd. Det beror på att vi vill binda till egenskaper som finns i koden bakom, vilket innebär att det behöver något sätt att hänvisa till sig själv. - Var och en av bindningarna på ComboBox har UserControls namn som
ElementName
. Detta är så att UserControl vet att titta på sig själv för att hitta bindningar. - Etiketten är inte träfftest synligt. Detta är för att ge användaren en illusion att etiketten är en del av ComboBox. Genom att ställa in
IsHitTestVisible=false
, tillåter vi användaren att sväva över eller klicka på etiketten - all inmatning skickas genom den till ComboBox nedan. - Etiketten använder en
InverseNullVisibility
omvandlare för att avgöra om den ska visa sig själv eller inte. Du kan hitta koden för detta längst ner i detta exempel.
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); }
}
}
I koden bakom avslöjar vi helt enkelt vilka egenskaper vi vill vara tillgängliga för programmeraren med denna UserControl. Tyvärr, eftersom vi inte har direkt tillgång till ComboBox utanför denna klass, måste vi exponera duplicerade egenskaper (till exempel MyItemsSource
för ComboBox's ItemsSource
). Detta är dock en mindre avvägning med tanke på att vi nu kan använda detta på liknande sätt som en infödd kontroll.
CustomComboBox
här kan CustomComboBox
UserControl användas:
<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>
Och slutresultatet:
Här är InverseNullVisibilityConverter som behövs för etiketten på UserControl, som bara är en liten variation på llls version :
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();
}
}