Как вызвать событие TextChanged в MVVM с помощью ICommand - PullRequest
0 голосов
/ 07 января 2020

Я использую 2 текстовых поля. Если пользователь вводит что-то в одно из текстовых полей, другое текстовое поле будет отключено. Если пользователь удалит весь текст в одном из текстовых полей, другое текстовое поле будет повторно включено.

Эти правила должны гарантировать, что только одно текстовое поле может содержать текст. Текстовое поле с текстом внутри - это текстовое поле поиска, которое слушает триггер кнопки поиска «Suchen».

Вот как выглядит вид:

enter image description here

Чтобы эти правила работали, я хочу использовать TextChanged-Events в качестве ICommands в соответствии со стандартами MVVM. Я попробовал, но он не делает то, что я хочу. Что оно делает? - Если я что-то наберу в текстовом поле «Artikelbezeichnung», текстовое поле «Lieferant» не будет отключено, а если я удалю весь текст внутри «Artikelbezeichnung», текстовое поле «Lieferant» отключит (и никогда не включит снова). Я считаю, что я не могу получить asp логи c этого странного поведения, и поэтому мне нужна ваша помощь. Я сократил код до минимума, чтобы вам было проще.

Что мне нужно изменить, чтобы мои правила работали? Пожалуйста, посмотрите на следующий код и помогите мне. Большое спасибо за попытку!

XAML-просмотр

 <StackPanel Height="423" VerticalAlignment="Bottom">
    <Label Name="lblArtikelbezeichnung" Content="Artikelbezeichnung:" Margin="20, 20, 20, 0"></Label>
    <TextBox Name="txtArtikelbezeichnung" 
             Width="Auto" 
             Margin="20, 0, 20, 0"
             IsEnabled="{Binding BezEnabled}"
             Text="{Binding BezText}">
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="TextChanged">
                <i:InvokeCommandAction Command="{Binding TextChangedBez}" />
            </i:EventTrigger>
            <i:EventTrigger EventName="KeyUp">
                <i:InvokeCommandAction Command="{Binding KeyUpBez}" />
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </TextBox>
    <!--TextChanged="txtArtikelbezeichnung_TextChanged" 
             KeyUp="txtArtikelbezeichnung_KeyUp"-->
    <Label Name="lblLieferant" Content="Lieferant:" Margin="20, 0, 20, 0"></Label>
    <TextBox Name="txtLieferant" 
             Width="Auto" 
             Margin="20, 0, 20, 0"
             IsEnabled="{Binding LiefEnabled}"
             Text="{Binding LiefText}">
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="TextChanged">
                <i:InvokeCommandAction Command="{Binding TextChangedLief}" />
            </i:EventTrigger>
            <i:EventTrigger EventName="KeyUp">
                <i:InvokeCommandAction Command="{Binding KeyUpLief}" />
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </TextBox>
        <!--TextChanged="txtLieferant_TextChanged" 
             KeyUp="txtLieferant_KeyUp"-->
    <Button Name="btnSuchen" 
            Content="Suchen" 
            Width="100" Height="25" 
            Margin="20, 10,240, 10" 
            Command="{Binding GefilterteSuche}">
    </Button>
...
<StackPanel>

Код позади

 using System.Windows;

namespace Lieferscheine
{
    /// <summary>
    /// Interaktionslogik für artikelHinzu.xaml
    /// </summary>
    public partial class artikelHinzu : Window
    {

        public artikelHinzu()
        {
            InitializeComponent();
            DataContext = new ArtikelHinzuViewModel();
        }     
    }
}

Посмотреть модель

public class ArtikelHinzuViewModel : INotifyPropertyChanged
{

    //ICommands
    public ICommand TextChangedLief => new DelegateCommand<object>(TextChangedLieferant);        
    public ICommand TextChangedBez => new DelegateCommand<object>(TextChangedBezeichnung);


    private bool _bezEnabled = true;
    private bool _liefEnabled = true;
    public bool BezEnabled
    {
        get
        {
            return _bezEnabled;
        }
        set
        {
            _bezEnabled = value;
            OnPropertyChanged("BezEnabled");
        }
    }
    public bool LiefEnabled
    {
        get 
        { 
            return _liefEnabled;
        }

        set
        {
            _liefEnabled = value;
            OnPropertyChanged("LiefEnabled");
        }
    }

    private string _bezText;
    private string _liefText;
    public string LiefText
    {
        get
        {
            return _liefText;
        }
        set
        {
            _liefText = value;
            OnPropertyChanged("LiefText");
        }
    }

    public string BezText
    {
        get
        {
            return _bezText;
        }
        set
        {
            _bezText = value;
            OnPropertyChanged("BezText");
        }
    }

    public void TextChangedBezeichnung(object param)
    {
        if (!String.IsNullOrWhiteSpace(BezText))
        {
            LiefEnabled = false;
        }
        else
        {
          LiefEnabled = true;
        }
    }

    public void TextChangedLieferant(object param)
    {
        if (!String.IsNullOrWhiteSpace(LiefText))
        {
           BezEnabled = false;
        }
        else
        {
            BezEnabled = true;
        }
    }
public event PropertyChangedEventHandler PropertyChanged;
    public virtual void OnPropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
        {
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    //Konstruktor
    public ArtikelHinzuViewModel()
    {

    }
}

1 Ответ

1 голос
/ 08 января 2020

Я считаю, что нежелательное поведение вызвано Event Racing.

Обратите внимание, что механизм привязки данных, по умолчанию , вызывает установщик свойства Text при LostFocus цели привязки ( Элемент пользовательского интерфейса). Но событие TextChanged было запущено до того, как TextBox потерял фокус. Это приводит к тому, что вашей команде не удается получить правильный лог c.

Быстрое решение будет

Text="{Binding BezText, UpdateSourceTrigger=PropertyChanged}">

Конечно, я не знаю вашей точной ситуации, но я не думаю, что необходимо использовать ICommand и System. Windows. Интерактивность даже в смысле MVVM. Вы могли бы рассмотреть следующее:

ViewModel

        public string LiefText
        {
            get
            {
                return _liefText;
            }
            set
            {
                _liefText = value;
                OnPropertyChanged("LiefText");

                if (!String.IsNullOrWhiteSpace(_liefText))
                    BezEnabled = false;
                else
                    BezEnabled = true;
            }
        }

        public string BezText
        {
            get
            {
                return _bezText;
            }
            set
            {
                _bezText = value;
                OnPropertyChanged("BezText");

                if (!String.IsNullOrWhiteSpace(_bezText))
                    LiefEnabled = false;
                else
                    LiefEnabled = true;
            }
        }

View

        <TextBox Name="txtArtikelbezeichnung" 
             Width="Auto" 
             Margin="20, 0, 20, 0"
             IsEnabled="{Binding BezEnabled}"
             Text="{Binding BezText, UpdateSourceTrigger=PropertyChanged}">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="KeyUp">
                    <i:InvokeCommandAction Command="{Binding KeyUpBez}" />
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </TextBox>

       <TextBox Name="txtLieferant" 
             Width="Auto" 
             Margin="20, 0, 20, 0"
             IsEnabled="{Binding LiefEnabled}"
             Text="{Binding LiefText, UpdateSourceTrigger=PropertyChanged}">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="KeyUp">
                    <i:InvokeCommandAction Command="{Binding KeyUpLief}" />
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </TextBox>
...