在WPF ComboBox中创建可替换的占位符文本

时间:2017-09-08 19:09:45

标签: c# wpf

假设我有一个组合框,其中的内容将是一些功能选项,我希望能够填写参数。例如,选项可能是

[ComboBox option menu drops down to show the following text options]
Foo(int x)
Bar(int y, int z)
HelloWorld(string q)

当用户选择了这些选项中的任何一个时,组合框将关闭选项菜单(正常)并显示所选选项。但是,我希望参数部分是一种预先突出显示的'文本块,点击后会突出显示该突出显示的焦点,以便您可以使用参数选择立即覆盖它。

1 个答案:

答案 0 :(得分:1)

Cheap'n'cheeesy,并没有梦想处理布拉德利的多个参数的情况:它只是选择了parens之间的一切。但它会处理您列出的案例。

在现实生活中,你当然希望用附加的行为来设置这个事件。

private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    var cb = (ComboBox)sender;

    var item = cb.SelectedItem as SelectMethodCallItem;

    //  This event is raised when user alters the text, but 
    //  SelectedItem will be null in that case. 
    if (item != null && item.HasSelection)
    {
        var edit = (TextBox)cb.Template.FindName("PART_EditableTextBox", cb);

        Action setsel = () =>
        {
            edit.SelectionStart = item.SelStart;
            edit.SelectionLength = item.SelLEngth;
        };
        //  the BeginInvoke/application idle gimmick is so it happens 
        //  after this event is over with, so the change we make isn't stepped on
        App.Current.Dispatcher.BeginInvoke(
            System.Windows.Threading.DispatcherPriority.ApplicationIdle, setsel);
    }
}

在现实生活中,您可以做一些更聪明,更健壮的东西来识别可替换的参数文本。

public class SelectMethodCallItem
{
    public SelectMethodCallItem(String text)
    {
        Text = text;
        SelStart = text.IndexOf('(');
        SelEnd = text.IndexOf(')');

        if (SelStart > -1 && SelEnd > -1)
        {
            ++SelStart;
            ++SelEnd;
        }
        else
        {
            SelStart = SelEnd = -1;
        }
    }

    public String Text { get; set; }
    public int SelStart { get; private set; }
    public int SelEnd { get; private set; }

    public int SelLEngth => (SelEnd - SelStart) - 1;

    public bool HasSelection => SelStart > -1 && SelEnd > -1;
}

XAML

<ComboBox
    IsEditable="True"
    ItemsSource="{Binding CBItems}"
    SelectionChanged="ComboBox_SelectionChanged" 
    DisplayMemberPath="Text"
    />

背后的代码

public Form()
{
    InitializeComponent();

    DataContext = new 
        {
            CBItems = new[] {
                new SelectMethodCallItem("sin(float x)"),
                new SelectMethodCallItem("cos(float x)"),
                new SelectMethodCallItem("foobar(string s)"),
            }
        };
}