Szukaj…


Uwagi

Zauważ, że UserControl bardzo różni się od Control. Jedną z głównych różnic jest to, że UserControl korzysta z pliku układu XAML w celu ustalenia, gdzie umieścić kilka pojedynczych elementów sterujących. Z drugiej strony kontrolka jest po prostu czystym kodem - w ogóle nie ma pliku układu. Pod pewnymi względami utworzenie niestandardowej Kontroli może być bardziej skuteczne niż utworzenie niestandardowej Kontroli użytkownika.

ComboBox z niestandardowym domyślnym tekstem

Ten niestandardowy UserControl pojawi się jako zwykły combobox, ale w przeciwieństwie do wbudowanego obiektu ComboBox, może pokazywać użytkownikowi domyślny ciąg tekstu, jeśli jeszcze nie dokonał wyboru.

Aby to osiągnąć, nasz UserControl będzie się składał z dwóch elementów sterujących. Oczywiście potrzebujemy faktycznego ComboBoxa, ale użyjemy również zwykłej Etykiety, aby wyświetlić domyślny tekst.


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>

Jak widać, ten pojedynczy UserControl jest w rzeczywistości grupą dwóch indywidualnych Kontrolek. To pozwala nam na pewną elastyczność, która nie jest dostępna w pojedynczym ComboBoxie.

Oto kilka ważnych rzeczy, na które należy zwrócić uwagę:

  • Sam UserControl ma zestaw x:Name . Wynika to z faktu, że chcemy powiązać z właściwościami znajdującymi się w kodzie, co oznacza, że potrzebuje jakiegoś sposobu na odwołanie się do siebie.
  • Każde wiązanie w ComboBox ma nazwę UserControl jako ElementName . Dzieje się tak, aby UserControl wiedział, że może spojrzeć na siebie, aby zlokalizować powiązania.
  • Etykieta nie jest widoczna przy trafieniu. Ma to dać złudzenie, że etykieta jest częścią ComboBox. Ustawiając IsHitTestVisible=false , uniemożliwiamy użytkownikowi najechanie myszką na lub kliknięcie Etykiety - wszystkie dane wejściowe są przekazywane do ComboBox poniżej.
  • Etykieta używa konwertera InverseNullVisibility celu ustalenia, czy powinna się wyświetlać, czy nie. Możesz znaleźć kod tego na dole tego przykładu.

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); }
    }
}

W ramach kodu po prostu ujawniamy, które właściwości chcemy być dostępne dla programisty za pomocą tego UserControl. Niestety, ponieważ nie mamy bezpośredniego dostępu do ComboBox spoza tej klasy, musimy ujawnić zduplikowane właściwości (na przykład MyItemsSource dla ComboBox's ItemsSource ). Jest to jednak niewielki kompromis, biorąc pod uwagę, że możemy teraz używać tego podobnie do kontroli rodzimej.


Oto, w jaki sposób można użyć CustomComboBox UserControl:

<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>

I efekt końcowy:

Rycina 1 wprowadź opis zdjęcia tutaj Rycina 3


Oto InverseNullVisibilityConverter potrzebny dla Label na UserControl, który jest tylko niewielką zmianą w wersji 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();
    }
}


Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow