Romain
Romain

Reputation: 103

Update combobox while using DisplayMemberPath

I am using WPF and MVVM light framework (and I am new in using them)

Here is the situation:

What I want to do is when the user clicks 'Save', the item title in the combobox gets updated too and the new value is displayed at that time. However, I do not know how to do that...

Some details on my implementation:

MainWindow.xaml

<ComboBox ItemsSource="{Binding SourceData}" SelectedItem="{Binding SelectedSourceData,Mode=TwoWay}" DisplayMemberPath="Title" />
<TextBlock Text="{Binding SelectedDataInTextFormat}"/>

MainWindow.xaml.cs

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        Closing += (s, e) => ViewModelLocator.Cleanup();
    }
}

MainViewModel.xaml

public class MainViewModel:ViewModelBase
{
  public ObservableCollection<Foo> SourceData{get;set;}
  public Foo SelectedSourceData 
  { 
    get{return _selectedFoo;}
    set{_selectedFoo=value; RaisePropertyChanged("SelectedSourceData"); }
  }

  public string SelectedDataInTextFormat
  {
    get{return _selectedDataInTextFormat;}
    set{_selectedDataInTextFormat=value; RaisePropertyChanged("SelectedDataInTextFormat");
  }
}

I would appreciate if anyone could help me on this one.

Thanks for your help.

Romain

Upvotes: 1

Views: 2042

Answers (3)

Bob.
Bob.

Reputation: 4002

Code:

public ObservableCollection<Foo> SourceData{get;set;}
public Foo SelectedSourceData 
{
    get{
        return _selectedFoo;
    }
    set{
        _selectedFoo=value;
        RaisePropertyChanged("SelectedSourceData");
    }
}

public string SelectedDataInTextFormat //Bind the text to the SelectedItem title
{
    get{
        return SelectedSourceData.Title
    }
    set{
        SelectedSourceData.Title=value;
        RaisePropertyChanged("SelectedDataInTextFormat");
    }
}

XAML:

<ComboBox ItemsSource="{Binding SourceData, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 
    SelectedItem="{Binding SelectedSourceData,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" DisplayMemberPath="Title" />
<TextBlock Text="{Binding SelectedDataInTextFormat, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>

Upvotes: 0

Clemens
Clemens

Reputation: 128060

You might simply update the SelectedSourceData property when SelectedDataInTextFormat changes:

public string SelectedDataInTextFormat
{
    get { return _selectedDataInTextFormat; }
    set
    {
        _selectedDataInTextFormat = value;
        RaisePropertyChanged("SelectedDataInTextFormat");

        SelectedSourceData = SourceData.FirstOrDefault(f => f.Title == _selectedDataInTextFormat)
    }
}

EDIT: In order to change the Title property of the currently selected Foo item in the ComboBox, you could implement INotifyPropertyChanged in your Foo class:

public class Foo : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private string title = string.Empty;
    public string Title
    {
        get { return title; }
        set
        {
            title = value;
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs("Title"));
            }
        }
    }
}

Then simply set the Title property of the selected item:

SelectedSourceData.Title = SelectedDataInTextFormat;

Upvotes: 1

sa_ddam213
sa_ddam213

Reputation: 43596

There is many ways to do this, This example takes advantage of the Button Tag property to send some data to the save button handler(or ICommand), Then we can set the TextBox UpdateSourceTrigger to Explicit and call the update when the Button is clicked.

Example:

Xaml:

<Window x:Class="WpfApplication8.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="105" Width="156" Name="UI">
    <Grid DataContext="{Binding ElementName=UI}">
        <StackPanel Name="stackPanel1">
            <ComboBox x:Name="combo" ItemsSource="{Binding SourceData}" DisplayMemberPath="Title" SelectedIndex="0"/>
            <TextBox x:Name="txtbox" Text="{Binding ElementName=combo, Path=SelectedItem.Title, UpdateSourceTrigger=Explicit}"/>
            <Button Content="Save" Tag="{Binding ElementName=txtbox}" Click="Button_Click"/>
        </StackPanel>
    </Grid>
</Window>

Code:

public partial class MainWindow : Window, INotifyPropertyChanged
{
    private ObservableCollection<Foo> _sourceData = new ObservableCollection<Foo>();

    public MainWindow()
    {
        InitializeComponent();
        SourceData.Add(new Foo { Title = "Stack" });
        SourceData.Add(new Foo { Title = "Overflow" });
    }

    public ObservableCollection<Foo> SourceData
    {
        get { return _sourceData; }
        set { _sourceData = value; }
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        var txtbx = (sender as Button).Tag as TextBox;
        txtbx.GetBindingExpression(TextBox.TextProperty).UpdateSource();
    }


    public event PropertyChangedEventHandler PropertyChanged;
    public void RaisePropertyChanged(string property)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(property));
        }
    }
}


public class Foo : INotifyPropertyChanged
{
    private string _title;
    public string Title
    {
        get { return _title; }
        set { _title = value; RaisePropertyChanged("Title"); }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    public void RaisePropertyChanged(string property)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(property));
        }
    }
}

Upvotes: 0

Related Questions