c# - 带有MVVM的WPF建议文本框

标签 c# wpf mvvm

我在WPF中有一个文本框,该文本框会根据字符串数组自动提示。但是,我已经在代码中找到了这一点,并试图在不违反MVVM的情况下重写整个程序,因为整个程序已经成为测试的噩梦。最好的方法是什么?附加到文本框的行为是唯一的方法吗?
请参阅下面的代码
XAML

<Window x:Class="Solutions.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Title="MainWindow" Height="450" Width="800">
<Grid>
    <TextBox VerticalAlignment="Center" HorizontalAlignment="Center" x:Name="SuggestionBox" Width="200"
             />
</Grid>

MainWindow.xaml.cs
using System.Linq;
using System.Windows;
using System.Windows.Controls;

namespace Solutions
{
    public partial class MainWindow : Window
    {
        private static readonly string[] SuggestionValues = {
            "England",
            "USA",
            "France",
            "Estonia"
        };

        public MainWindow()
        {
            InitializeComponent();
            SuggestionBox.TextChanged += SuggestionBoxOnTextChanged;
        }

        private string _currentInput = "";
        private string _currentSuggestion = "";
        private string _currentText = "";

        private int _selectionStart;
        private int _selectionLength;
        private void SuggestionBoxOnTextChanged(object sender, TextChangedEventArgs e)
        {
            var input = SuggestionBox.Text;
            if (input.Length > _currentInput.Length && input != _currentSuggestion)
            {
                _currentSuggestion = SuggestionValues.FirstOrDefault(x => x.StartsWith(input));
                if (_currentSuggestion != null)
                {
                    _currentText = _currentSuggestion;
                    _selectionStart = input.Length;
                    _selectionLength = _currentSuggestion.Length - input.Length;

                    SuggestionBox.Text = _currentText;
                    SuggestionBox.Select(_selectionStart, _selectionLength);
                }
            }
            _currentInput = input;
        }
    }
}

最佳答案

您有3种选择:

  • 附加属性(很酷,但是在我看来,这有点复杂)
  • 使用将获取建议
  • 的函数的依赖项属性创建新类SuggestionTextBox : TextBox
  • 与可编辑的ComboBox一起使用,几乎可以立即使用,但是您仍然必须创建SuggestionBox类。

  • 创建新的类可让您重新体验和完全控制。我将ReactiveUI用作我的MVVM框架,该框架为您提供了强类型的异步命令。
    因此,代码概述为:
    public class SuggestionBox : TextBox // you can easily go with ComboBox here, and even have xaml file if you want fancier UI
    {
       public ReactiveCommand<string, string[]> FetchSuggestionsCommand {get;set;} // this should dependency property, left out for brevity
    
       public ObservableColection<string> Suggestions {get;} // also dependency property
    
    
       public SuggestionBox()
       {
           this.WhenAnyValue(x => x.Text).InvokeCommand(FetchSuggestionsCommand); // this is strongly typed so you get compilation error if types don't match
           
           FetchSuggestionsCommand.Subscribe(suggestions => 
                    {
                        Suggestions.Clear();
                        Suggestions.AddRange(suggestions);
                    }); // a little more subscribtion management magic required, but I just want to show the idea
        // rest of your logic for displaying suggestions
        }
    }
    
    然后在其他一些XAML中:
    <SuggestionBox FetchSuggestionsCommand="{Binding ViewModel.FetchSuggestionsFromWeb}"/>
    
    现在,您可以很好地在获取逻辑(它存在于其他ViewModel中,在ReactiveUI中甚至可以在那里处理错误)与 View 之间分离(它仅存在于SuggestionBox类中,而不在乎逻辑如何获取建议)。
    最后的一句话:在xaml.cs中包含代码并不违反MVVM。确实,您可以在那里做一些很酷的事情(例如,如果发生某些事情,将焦点设置到某个元素上,则在ViewModel中设置错误)。 MVVM是一个非常酷的模式,一旦您掌握了这个主意,就没有那么严格了。

    关于c# - 带有MVVM的WPF建议文本框,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62560465/

    相关文章:

    c# - 使用 "POST"方法从 .net 服务器(C# 和 json 格式)获取响应到 Objective-c 问题

    c# - 打开按钮上的 View ,单击MVVM

    c# - 如何在 MainWindow.xaml 中绑定(bind)多个 ViewModel?

    wpf - Visual Studio 2012 - 性能分析 Prism 应用程序

    c# - 无法从 ViewModel 绑定(bind)到模型的成员

    c# - MVVM 刷新 System.Windows.Controls.Grid 中的只读文本框

    c# - 谁能指出任何好的 MVP 文章/教程的方向?

    c# - Google 帐户问题 - 无法在电子表格上书写

    c# - 如何通过 $MetricsCapacityBlob 获取 blob 大小

    wpf - 为什么在ActivateItem之后没有调用Caliburn.Micro(与modern-ui一起使用)的OnActivate?