سؤال

I have a text box which is bound to a list box through XAML, the text box is also bound to a view model, multibinding is used to obtain this, see below.

The Idea is that the selected item has to be modified before it is used in the view model.

I am not happy with this code, to complex for such a simple task. Each binding works perfectly alone. Which simple way can be used to select an element modify it and use the modified string for further processing in the view model?

--------------The XAML--------------

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfApplication1"
    Title="MainWindow" Height="350" Width="525">
<Window.Resources>
    <local:TheMultiValueConverter x:Key="theConverter"/>
</Window.Resources>
<StackPanel>
    <TextBox Name="textBox">
        <TextBox.Text>
            <MultiBinding Converter="{StaticResource theConverter}" Mode="OneWay">
                <Binding/>
                <Binding ElementName="textBox" Path="Text"/>
                <Binding ElementName="listBox" Path="SelectedItem" Mode="OneWay"/>
            </MultiBinding>
        </TextBox.Text>
    </TextBox>
    <ListBox Name="listBox" ItemsSource="{Binding Data}" />
</StackPanel>
</Window>

--------------The view model--------------

public class ViewModel : INotifyPropertyChanged
{
  string modified;
  public string Modified
  {
    get { return modified; }
    set
    {
      if (modified != value)
      {
        modified = value;
        NotifyPropertyChanged("Modified");
      }
    }
  }

  List<string> data = new List<string> { "Test1", "Test2" };
  public List<string> Data
  {
    get { return data; }
  }

  public event PropertyChangedEventHandler PropertyChanged;
  private void NotifyPropertyChanged(string propertyName)
  {
    PropertyChangedEventHandler handler = PropertyChanged;
    if (handler != null)
    {
      handler(this, new PropertyChangedEventArgs(propertyName));
    }
  }
}

--------------The value converter--------------

public class TheMultiValueConverter : IMultiValueConverter
{
  public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
  {
    var viewModel = values[0] as ViewModel;

    if (viewModel != null)
    {
      viewModel.Modified = (string)values[1];

      if (string.IsNullOrWhiteSpace(values[1].ToString()))
        return values[2];
      else
        return values[1];
    }

    return null;
  }

  public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
  {
    throw new NotImplementedException();
  }
}
هل كانت مفيدة؟

المحلول

If you follow MVVM to the letter, you would end up with an additional property in your VM. So you'd have Data for the binding source, SelectedItem for the current selected item, and ModifiedItem for the value in the textbox. Then in your XAML, each of your controls would only be bound to the VM, rather than being bound to each other in any way. (I usually find that when controls are bound to one another, that means the VM is a little underdeveloped. Of course, sometimes simplicity wins out over architectural purism.)

<Window ...>
    ...
    <StackPanel>
        <TextBox Name="textBox" Text="{Binding ModifiedItem}" />
        <ListBox Name="listBox" ItemsSource="{Binding Data}" SelectedItem="{Binding SelectedItem}" />
    </StackPanel>
</Window>

Note that it would be up to the VM to set ModifiedItem when the SelectedItem property changes. Then the TextBox will write back to that same property due to the two-way binding on the Text property.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top