简体   繁体   English

WPF ListBox自定义项

[英]WPF ListBox custom item

I want to have a "Custom" item inside a ListBox, so that the user can enter custom values apart from the preset selectable values. 我想在列表框内有一个“自定义”项,以便用户可以输入除预设可选值之外的自定义值。

Here's my XAML code: 这是我的XAML代码:

        <ListBox SelectedValue="{Binding SomeValue}"
                 SelectedValuePath="Tag"
                 Style="{StaticResource HorizontalRadioButtonList}">
            <!-- style from http://stackoverflow.com/a/4120034/1813487 -->
            <ListBoxItem Tag="10" 
                     Content="10"/>
            <ListBoxItem Tag="20" 
                     Content="20"/>
            <ListBoxItem Tag="30" 
                     Content="30"/>
            <ListBoxItem x:Name="CustomListBoxItem">
                <TextBox Text="{Binding ElementName=CustomListBoxItem, 
                                        Mode=OneWayToSource, 
                                        UpdateSourceTrigger=PropertyChanged, 
                                        Path=Tag}"/>
            </ListBoxItem>
        </ListBox>
        <TextBlock Text="{Binding SomeValue}"/>

How to make SomeValue update as soon as the user enters something in the TextBox? 用户在TextBox中输入内容后,如何使SomeValue更新? Currently the ListBox does not detect that the Tag changed, and does not update SomeValue. 当前,ListBox不会检测到Tag更改,并且不会更新SomeValue。

I think you can achieve that using a behavior attached to the TextBox, where you sign the TextChanged event and everytime it is triggered you could set the ListBoxItem's tag to the TextBox's text. 我认为您可以通过使用附加到TextBox的行为来实现此目的,在该行为上对TextChanged事件进行签名,并在每次触发该事件时,都可以将ListBoxItem的标记设置为TextBox的文本。

I did something similar to that, but using Microsoft.Expression.Interactivity: 我做了类似的事情,但是使用了Microsoft.Expression.Interactivity:

<ListBoxItem x:Name="UniqueValue" Tag="40">
    <TextBox x:Name="TextBox" Text="40">
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="TextChanged">
                <ei:ChangePropertyAction PropertyName="Tag"
                                                             TargetObject="{Binding ElementName=UniqueValue}"
                                                             Value="{Binding Text,
                                                                             ElementName=TextBox}" />

                <ei:ChangePropertyAction PropertyName="SomeValue"
                                                             TargetObject="{Binding}"
                                                             Value="{Binding Text,
                                                                             ElementName=TextBox,
                                                                             Converter={StaticResource StringToIntConverter}}" />
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </TextBox>
</ListBoxItem>

Basically, everytime the text is changed, the property Tag will have its value set to the written text, and after that (to keep the selection of the ListBoxItem) the viewmodel's property SomeValue has its value set the same text. 基本上,每次更改文本时,属性Tag的值都将设置为书面文本,然后(为了保持对ListBoxItem的选择),视图模型的属性SomeValue的值将设置为相同的文本。

Namespaces: 命名空间:

    xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"

Assemblies required: 需要组装:

System.Windows.Interactivity
Microsoft.Expression.Interactions

Here's how I did it, it's not the perfect solution either: 这是我的操作方式,也不是完美的解决方案:

XAML: XAML:

<ListBox SelectedValue="{Binding SomeValue}"
             SelectedValuePath="Tag"
             Style="{StaticResource HorizontalRadioButtonList}"
             x:Name="CustomListBox">
        <!-- ...items... -->
        <ListBoxItem x:Name="CustomListBoxItem">
            <TextBox Text="{Binding ElementName=CustomListBoxItem, 
                                    Mode=OneWayToSource, 
                                    UpdateSourceTrigger=PropertyChanged, 
                                    Path=Tag}"
                     TextChanged="UpdateCustomValue"
                     x:Name="CustomTextBox"/>
        </ListBoxItem>
    </ListBox>
    <TextBlock Text="{Binding SomeValue}"/>

Code: 码:

private void UpdateUniqueValue(object sender, TextChangedEventArgs e)
{
    var listBox = sender == CustomTextBox? CustomListBox: null;
    if (listBox != null)
    {
        var textBox = (TextBox) sender;
        try // so that invalid values are not allowed
        {
            listBox.SelectedValue = textBox.Text;
        }
        catch
        {
            textBox.Text = listBox.SelectedValue.ToString();
        }
    }
}

It is a workaround and does not take into account validators either, but at least does not allow invalid values to be entered. 这是一种解决方法,也没有考虑验证器,但至少不允许输入无效值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM