2013-07-22 3 views
0

У меня есть текстовое поле, которое привязано к списку с помощью XAML, текстовое поле также привязано к модели представления, многосвязывание используется , чтобы получить это, см. Ниже.Multi binding, лучшее решение?

Идея в том, что выбранный элемент необходимо изменить до его использования. используется в модели представления.

Я не доволен этим кодом, сложным для такой простой задачи. Каждое связывание работает совершенно отдельно. Какой простой способ можно использовать , чтобы выбрать элемент, изменить его и использовать модифицированную строку для дальнейшей обработки в модели просмотра?

-------------- Часть 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> 

--------- ----- Модель обзора --------------

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)); 
    } 
    } 
} 

-------------- Преобразователь ценности ------- ----------

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(); 
    } 
} 

ответ

4

Если вы следуете MVVM на письмо, вы получите дополнительное свойство в своей виртуальной машине. Таким образом, у вас есть Data для источника привязки, SelectedItem для текущего выбранного элемента и ModifiedItem для значения в текстовом поле. Затем в вашем XAML каждый из ваших элементов управления будет привязан только к виртуальной машине, а не связан друг с другом каким-либо образом. (Я обычно считаю, что когда элементы управления связаны друг с другом, это означает, что виртуальная машина немного недоразвиты. Конечно, иногда простота побеждает архитектурного пуризма.)

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

Обратите внимание, что это будет до VM установить ModifiedItem при изменении свойства SelectedItem. Затем TextBox будет возвращаться к тому же свойству из-за двусторонней привязки к свойству Text.

+0

Отлично, спасибо Gunter :) – Bertrand

Смежные вопросы