Как установить maxlength для combobox в WPF?

Как установить maxlength в combobox, который имеет стиль, применяемый к нему.

Спасибо

Ответы

Ответ 1

При использовании DependencyProperty мы можем установить максимальную длину поля со списком без изменения вашего стиля/шаблона.

public class EditableComboBox
{

    public static int GetMaxLength(DependencyObject obj)
    {
        return (int)obj.GetValue(MaxLengthProperty);
    }

    public static void SetMaxLength(DependencyObject obj, int value)
    {
        obj.SetValue(MaxLengthProperty, value);
    }

    // Using a DependencyProperty as the backing store for MaxLength.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty MaxLengthProperty = DependencyProperty.RegisterAttached("MaxLength", typeof(int), typeof(EditableComboBox), new UIPropertyMetadata(OnMaxLenghtChanged));

    private static void OnMaxLenghtChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
    {
        var comboBox = obj as ComboBox;
        if (comboBox == null) return;

        comboBox.Loaded +=
            (s, e) =>
            {
                var textBox = comboBox.FindChild(typeof(TextBox), "PART_EditableTextBox");
                if (textBox == null) return;

                textBox.SetValue(TextBox.MaxLengthProperty, args.NewValue);
            };
    }
}

Пример использования:

<ComboBox ComboboxHelper:EditableComboBox.MaxLength="50" />

Где ComboboxHelper:

XMLNS: ComboboxHelper = "clr- Пространство имен: yourNameSpace; сборка = yourAssembly"

метод comboBox.FindChild(...) размещен здесь.

Ответ 2

Или вы можете использовать событие GotFocus или Loaded в поле со списком для установки maxlength.Если значение maxlength слишком сильно изменяется во время выполнения, вы можете использовать загруженное событие или использовать событие gotfocus

<ComboBox Height="30" IsEditable="True" Loaded="ComboBox_Loaded"/>

и в соответствующем событии...

   var obj = (ComboBox)sender;
    if (obj != null)
    {
        var myTextBox = (TextBox)obj.Template.FindName("PART_EditableTextBox",obj);
        if (myTextBox != null)
        {
            myTextBox.MaxLength = maxLength;
        }
    }

Ответ 3

Вы правы. Для текстового поля есть максимальная длина, но не для combobox. Вы должны катиться самостоятельно, используя текстовое поле в качестве посредника. Вот код:

public int MaxLength {get; set;}
protected override void OnGotFocus(System.Windows.RoutedEventArgs e)
{
    base.OnGotFocus(e);
    TextBox thisTextBox = (TextBox)base.GetTemplateChild("PART_EditableTextBox");
    if (thisTextBox != null)
        thisTextBox.MaxLength = MaxLength;
}

Ответ 4

Этот TextBox подходит к нулю. Приведенный стиль выглядит следующим образом.

<ControlTemplate x:Key="ComboBoxToggleButton" TargetType="ToggleButton">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="{Binding Path=(local:ToggleComboBox.Width),
                     RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ComboBox}}}" />
            </Grid.ColumnDefinitions>
            <Border x:Name="Border" 
                    Grid.Column="1"
                    CornerRadius="2"
                    Background="#CCFFCC"
                    BorderBrush="#000080"
                    BorderThickness="4" />

            <Border Grid.Column="0"
                    CornerRadius="8,8,8,8" 
                    Margin="0" 
                    Background="#CCFFCC" 
                    BorderBrush="#000080"
                    BorderThickness="4,4,4,4" />

            <Image x:Name="Arrow"
                   Grid.Column="1"     
                   Source="Arrow.png" Margin="4,4,4,4"
                   HorizontalAlignment="Center"
                   VerticalAlignment="Center"/>
        </Grid>
        <ControlTemplate.Triggers>
            <Trigger Property="ToggleButton.IsMouseOver" Value="true">
                <Setter TargetName="Border" Property="Background" Value="{StaticResource DarkBrush}" />
            </Trigger>
            <Trigger Property="ToggleButton.IsChecked" Value="true">
                <Setter TargetName="Border" Property="Background" Value="{StaticResource PressedBrush}" />
            </Trigger>
            <Trigger Property="IsEnabled" Value="False">
                <Setter TargetName="Border" Property="Background" Value="{StaticResource DisabledBackgroundBrush}" />
                <Setter TargetName="Border" Property="BorderBrush" Value="{StaticResource DisabledBorderBrush}" />
                <Setter Property="Foreground" Value="{StaticResource DisabledForegroundBrush}"/>
                <!--<Setter TargetName="Arrow" Property="Fill" Value="{StaticResource DisabledForegroundBrush}" />-->
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>

    <ControlTemplate x:Key="ComboBoxTextBox" TargetType="TextBox">
        <Border x:Name="PART_ContentHost" Focusable="False" Background="{TemplateBinding Background}" />
    </ControlTemplate>


    <Style x:Key="ComboBoxStyle" TargetType="ComboBox">
        <Setter Property="SnapsToDevicePixels" Value="true"/>
        <Setter Property="OverridesDefaultStyle" Value="true"/>
        <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
        <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
        <Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
        <Setter Property="MinWidth" Value="120"/>
        <Setter Property="MinHeight" Value="20"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="ComboBox">
                    <Grid>
                        <ToggleButton Name="ToggleButton" 
                                      Template="{StaticResource ComboBoxToggleButton}" 
                                      Grid.Column="2" 
                                      Focusable="false"
                                      IsChecked="{Binding Path=IsDropDownOpen,
                                                          Mode=TwoWay,
                                                          RelativeSource={RelativeSource TemplatedParent}}"
                                      ClickMode="Press"/>

                        <ContentPresenter Name="ContentSite"
                                          IsHitTestVisible="False" 
                                          Content="{TemplateBinding SelectionBoxItem}"
                                          ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}"
                                          ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"
                                          Margin="9,2,28,2"
                                          VerticalAlignment="Center"
                                          HorizontalAlignment="Left" />

                        <TextBox x:Name="PART_EditableTextBox"
                                 Style="{x:Null}" 
                                 Template="{StaticResource ComboBoxTextBox}" 
                                 HorizontalAlignment="Left" 
                                 VerticalAlignment="Center" 
                                 Margin="3,3,23,3"
                                 Focusable="True" 
                                 Background="Transparent"
                                 Visibility="Hidden"
                                 IsReadOnly="{TemplateBinding IsReadOnly}"/>

                        <Popup Name="Popup"
                               Placement="Bottom"
                               IsOpen="{TemplateBinding IsDropDownOpen}"
                               AllowsTransparency="True" 
                               Focusable="False"
                               PopupAnimation="Slide">

                            <Grid Name="DropDown"
                                  SnapsToDevicePixels="True"             
                                  MinWidth="{TemplateBinding ActualWidth}"
                                  MaxHeight="{TemplateBinding MaxDropDownHeight}">

                                <Border x:Name="DropDownBorder"
                                        Background="#CCFFCC" 
                                        BorderBrush="#000080"
                                        BorderThickness="2"/>

                                <ScrollViewer Margin="4,6,4,6" SnapsToDevicePixels="True">
                                    <ScrollViewer.Resources>
                                        <sys:Double x:Key="{x:Static SystemParameters.VerticalScrollBarWidthKey}">25</sys:Double>
                                    </ScrollViewer.Resources>                                    
                                    <StackPanel IsItemsHost="True" />
                                </ScrollViewer>
                            </Grid>
                        </Popup>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="HasItems" Value="false">
                            <Setter TargetName="DropDownBorder" Property="MinHeight" Value="95"/>
                        </Trigger>
                        <Trigger Property="IsEnabled" Value="false">
                            <Setter Property="Foreground" Value="{StaticResource DisabledForegroundBrush}"/>
                        </Trigger>
                        <Trigger Property="IsGrouping" Value="true">
                            <Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
                        </Trigger>
                        <Trigger SourceName="Popup" Property="Popup.AllowsTransparency" Value="true">
                            <Setter TargetName="DropDownBorder" Property="CornerRadius" Value="4"/>
                            <Setter TargetName="DropDownBorder" Property="Margin" Value="0,2,0,0"/>
                        </Trigger>
                        <Trigger Property="IsEditable" Value="true">
                            <Setter Property="IsTabStop" Value="false"/>
                            <Setter TargetName="PART_EditableTextBox" Property="Visibility" Value="Visible"/>
                            <Setter TargetName="ContentSite" Property="Visibility" Value="Hidden"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
        <Setter Property="ItemContainerStyle" >
            <Setter.Value>
                <Style TargetType="{x:Type ComboBoxItem}">
                    <Setter Property="FontSize" Value="20" />
                </Style>
            </Setter.Value>
        </Setter>
    </Style>

Ответ 5

Я нашел легкое решение через XAML. В ресурсах comboBox мы можем установить стиль для текстового поля и через setter set maxlenth.

<ComboBox Name="comboBox" Width="100" IsEditable="True">
<ComboBox.Resources>
<Style TargetType="{x:Type TextBox}"> 
    <Setter Property="MaxLength" Value="yourValue"></Setter> 
</Style>
</ComboBox.Resources>
</ComboBox>

EDIT: Это работает с Actipro ComboBox. Для обычного comboBox, чтобы сделать эту работу, посмотрите здесь

Ответ 6

Я использовал событие PreviewKeyDown, очень просто + вы можете показать предупреждение или что-то еще.
Зарегистрируйте метод ниже в ComboBox.PreviewKeyDown + = event,
Событие KeyDown не срабатывает, если пользователь нажимает "Пробел".

private void ComboBox_PreviewKeyDown(object sender, KeyEventArgs e)
{
    if (ComboBox.Text.Length > 19) // allow max 20 chars
    {
        if (e.Key != Key.Back) // allow removing chars
        {
            e.Handled = true; // block any additional key press if there is more than allowed max
            System.Media.SystemSounds.Beep.Play(); // optional: beep to let user know he is out of space :)
        }
    }
}