WPF Caliburn.Micro: Binding DisplayMemberPath on ChildViewModel - wpf

I use VS2013, WPF 4.5, Caliburn Micro 2.0.2. This is a sample project of mine.
My ShellViewModel has base class Conductor and has collection of model (a property) called Vehicles. I created also ChildViewModel that has base class Screen and a property called ParentVm, which contains its parent. In my real project I have surely more than one child viewmodel (thus, > 1 screens)
The model (class Vehicle) contains properties: Manufacturer, Model and Type.
How can I bind DisplayMemberPath of ListBox in ChildView which has ItemsSource="ParentVm.Vehicles", so the ListBox can show the Manufacturer of class Vehicle?
Following is my sample code. Please feel free to modify it to show me the solution. Thank you in advance.
public class Vehicle : PropertyChangedBase
{
public String Manufacturer { get; set; }
public String Model { get; set; }
public String Type { get; set; }
}
ShellViewModel
public class ShellViewModel : Conductor<Screen>, IHaveActiveItem
{
public ChildViewModel ChildVm { get; private set; }
public ObservableCollection<Vehicle> Vehicles { get; set; }
public ShellViewModel()
{
DisplayName = "Shell Window";
ChildVm = new ChildViewModel(this);
Vehicles = new ObservableCollection<Vehicle>();
SetData();
}
public void DisplayChild()
{
ActivateItem(ChildVm);
}
private void SetData()
{ // fill collection with some sample data
vh = new Vehicle();
vh.Manufacturer = "Chevrolet";
vh.Model = "Spark";
vh.Type = "LS";
Vehicles.Add(vh);
}
}
ShellView
<UserControl x:Class="CMWpfConductorParentChild.Views.ShellView"
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"
d:DesignHeight="300"
d:DesignWidth="300"
mc:Ignorable="d">
<Grid Width="300" Height="300" HorizontalAlignment="Center"
ShowGridLines="True">
<Grid.RowDefinitions>
<RowDefinition Height="2*" />
<RowDefinition Height="10*" />
</Grid.RowDefinitions>
<Button x:Name="DisplayChild"
Grid.Row="0" Width="120" Height="40"
HorizontalContentAlignment="Center"
Content="Display Child View" />
<ContentControl x:Name="ActiveItem" Grid.Row="1" />
</Grid>
</UserControl>
ChildViewModel
public class ChildViewModel : Screen
{
public ShellViewModel ParentVm { get; private set; }
public ChildViewModel(ShellViewModel parent)
{
ParentVm = parent;
}
}
ChildView (the binding of DisplayMemberPath below doesn't work)
<UserControl x:Class="CMWpfConductorParentChild.Views.ChildView"
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"
d:DesignHeight="300"
d:DesignWidth="300"
mc:Ignorable="d">
<Grid Width="300" Height="300">
<ListBox DisplayMemberPath="Manufacturer" ItemsSource="ParentVm.Vehicles" />
</Grid>
</UserControl>

You need to add the 'Binding' keyword to the 'ItemsSource' property:
<ListBox DisplayMemberPath="Manufacturer" ItemsSource="{Binding ParentVm.Vehicles}" />
I've modified your example to show how you can bind properties to the child view based on convention.
ShellViewModel
public class ShellViewModel : Screen, IShell
{
private readonly ChildViewModel _ChildView;
private readonly IEventAggregator _Aggregator;
public IList<Vehicle> vehicles = new List<Vehicle>();
public ShellViewModel(IEventAggregator aggregator, ChildViewModel childView)
{
if (aggregator == null)
throw new ArgumentNullException("aggregator");
_Aggregator = aggregator;
if (childView == null)
throw new ArgumentNullException("childView");
_ChildView = childView;
DisplayName = "Shell Window";
}
public ChildViewModel ChildView
{
get { return _ChildView; }
}
public void DisplayChild()
{
var vh = new Vehicle() { Manufacturer = "Chevrolet", Model = "Spark", Type = "LS" };
vehicles.Add(vh);
_Aggregator.PublishOnUIThreadAsync(new ShowChildViewEvent(vehicles));
}
}
ShellView
<UserControl x:Class="CaliburnDemo.ShellView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:cal="http://www.caliburnproject.org">
<Grid Width="300" Height="300" HorizontalAlignment="Center"
ShowGridLines="True">
<Grid.RowDefinitions>
<RowDefinition Height="2*" />
<RowDefinition Height="10*" />
</Grid.RowDefinitions>
<Button x:Name="DisplayChild"
Grid.Row="0" Width="120" Height="40"
HorizontalContentAlignment="Center"
Content="Display Child View" />
<ContentControl cal:View.Model="{Binding ChildView}" Grid.Row="1" />
</Grid>
ChildViewModel
public class ChildViewModel : Screen, IHandle<ShowChildViewEvent>
{
private BindableCollection<Vehicle> _Vehicles;
private readonly IEventAggregator _Aggregator;
public ChildViewModel(IEventAggregator aggregator)
{
if (aggregator == null)
throw new ArgumentNullException("aggregator");
_Aggregator = aggregator;
_Aggregator.Subscribe(this);
}
public BindableCollection<Vehicle> Vehicles
{
get { return _Vehicles; }
set
{
_Vehicles = value;
NotifyOfPropertyChange(() => Vehicles);
}
}
public void Handle(ShowChildViewEvent message)
{
Vehicles = new BindableCollection<Vehicle>(message.Vehicles);
}
}
ChildView
<UserControl x:Class="CaliburnDemo.ChildView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<ListBox x:Name="Vehicles" DisplayMemberPath="Manufacturer" />
</Grid>
ShowChildViewEvent
public class ShowChildViewEvent
{
public ShowChildViewEvent(IList<Vehicle> vehicles)
{
Vehicles = vehicles;
}
public IList<Vehicle> Vehicles { get; private set; }
}
IShell is an empty interface used for resolving the root view from the container. You can find more on conventions in Caliburn here:
Caliburn Conventions

Related

WPF How to bind object from window to custom user control

I need to create a custom user control and pass it from the main window an object. I need to display the object's attribute inside the user control, how can i do it? Thanks in advance.
EDIT: This is my code, what i'm doing wrong?
My custom control:
public partial class DetailsComponent : UserControl
{
public static readonly DependencyProperty ModelProperty = DependencyProperty.Register("Model", typeof(bool), typeof(DetailsComponent), new PropertyMetadata(null));
public ModelClass Model
{
get { return (ModelClass)GetValue(ModelProperty); }
set
{
SetValue(ModelProperty, value);
}
}
public DetailsComponent()
{
InitializeComponent();
DataContext = this;
}
}
usercontrol.xaml.cs:
<UserControl x:Class="WpfApp3.DetailsComponent"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfApp3"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<StackPanel>
<TextBlock Text="{Binding Name}"></TextBlock></TextBlock>-->
</StackPanel>
</Grid>
MainWindows.xaml:
<Window x:Class="WpfApp3.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"
xmlns:local="clr-namespace:WpfApp3" xmlns:custom="clr-namespace:LoadingSpinnerControl;assembly=LoadingSpinnerControl" xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<local:DetailsComponent Model="{Binding Model}"></local:DetailsComponent>
</Grid>
MainWindows.xaml.cs:
public partial class MainWindow : Window, INotifyPropertyChanged
{
ModelClass Model = null;
public MainWindow()
{
InitializeComponent();
Model = new ModelClass("hi", "hi", "hi");
DataContext = this;
}
}
ModelClass.cs:
public class ModelClass
{
public ModelClass(string name, string description, string city)
{
Name = name;
Description = description;
City = city;
}
public string Name { get; set; }
public string Description { get; set; }
public string City { get; set; }
}
Model must be defined as a public property for you to be able to bind to it:
public partial class MainWindow : Window
{
public ModelClass Model { get; }
public MainWindow()
{
InitializeComponent();
Model = new ModelClass("hi", "hi", "hi");
DataContext = this;
}
}
The DetailsModel should not set its own DataContext property because then you cannot bind to the Model property of its inherited DataContext:
public partial class DetailsComponent : UserControl
{
public static readonly DependencyProperty ModelProperty =
DependencyProperty.Register("Model", typeof(ModelClass), typeof(DetailsComponent), new PropertyMetadata(null));
public ModelClass Model
{
get { return (ModelClass)GetValue(ModelProperty); }
set { SetValue(ModelProperty, value); }
}
public DetailsComponent()
{
InitializeComponent();
}
}
You could bind to the Name property of the Model dependency property using a RelativeSource binding:
<UserControl x:Class="WpfApp3.DetailsComponent"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfApp3"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<StackPanel>
<TextBlock Text="{Binding Model.Name,
RelativeSource={RelativeSource AncestorType=UserControl}}" />
</StackPanel>
</Grid>
</UserControl

WPF ComboBoxAdaptor does not display the ComboBox property

https://stackoverflow.com/a/36192552/9387175
In this answer the user suggests that the comboBoxAdaptor can be used to add an item to a combo box even if it does not exist in the item source. I do in fact see that it is working in the code, but I can't figure out why it refuses to display. The normal combo box functions correctly in the below example, the comboBoxAdaptor is not visible. Am I missing something like styles or templates? I can't seem to find the right combination.
My xaml:
<Window x:Class="WpfApp1.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"
xmlns:adapters="clr-namespace:WpfApp1.Adapters"
mc:Ignorable="d"
Title="MainWindow"
Height="200"
Width="650">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="210" />
<ColumnDefinition Width="210" />
</Grid.ColumnDefinitions>
<adapters:ComboBoxAdaptor Grid.Column="0"
AllowNull="False"
Height="80"
ItemsSource="{Binding Path=DataEntries}"
SelectedItem="{Binding Path=DataEntry}">
<ComboBox Height="80" />
</adapters:ComboBoxAdaptor>
<ComboBox Grid.Column="1"
Height="80"
ItemsSource="{Binding Path=DataEntries}"
SelectedItem="{Binding Path=DataEntry}"
DisplayMemberPath="Name"
SelectedValuePath="Name" />
</Grid>
</Window>
My Code:
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;
namespace WpfApp1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
SampleViewModel vm = new SampleViewModel();
DataContext = vm;
}
}
public class SampleDataClass
{
public string Name { get; set; }
public SampleDataClass(string name)
{
Name = name;
}
}
public class SampleViewModel : INotifyPropertyChanged
{
private readonly IList<SampleDataClass> _dataEntries;
private string _dataEntry;
public event PropertyChangedEventHandler PropertyChanged;
public SampleViewModel()
{
IList<SampleDataClass> list = new List<SampleDataClass>();
list.Add(new SampleDataClass("tools"));
list.Add(new SampleDataClass("set"));
list.Add(new SampleDataClass("sort"));
list.Add(new SampleDataClass("flap"));
_dataEntries = list;
}
public IList<SampleDataClass> DataEntries
{
get { return _dataEntries; }
}
public string DataEntry
{
get
{
return _dataEntry;
}
set
{
if (_dataEntry == value) {return;}
_dataEntry = value;
OnPropertyChanged("DataEntry");
}
}
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Turns out that I was missing the style that links the ComboBox to the content of the ContentControl (ComboBoxAdaptor)
Style Example
<Style TargetType="adapters:ComboBoxAdaptor">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="adapters:ComboBoxAdaptor">
<ContentPresenter Content="{TemplateBinding ComboBox}"
Margin="{TemplateBinding Padding}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Binding a property inside observerList in wpf

I am writing an application in C#, WPF, XAML using MVVM patterm.
After many examples that I founded online the data that I try to Bind to the UI is not shown in the screen.
My architecture is : In the MainViewModel I have an ObserverList from type family,
in Family class I have an ObserverList from type Child,
in Child class I have Name.
How to Bind the Child Name in to TextBlock?
Some examples that I founded:
https://msdn.microsoft.com/en-us/library/aa970558%28v=vs.110%29.aspxv
<Window x:Class="DataTemplates.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:DataTemplates"
Title="MainWindow"
Height="350"
Width="525">
<Window.Resources>
<DataTemplate x:Key="MyDataTemplate"
DataType="local:MyData">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0"
Text="First Name: " />
<TextBlock Grid.Column="1"
Text="{Binding Path=FirstName}" />
<TextBlock Grid.Column="2"
Text="Last Name: " />
<TextBlock Grid.Column="3"
Text="{Binding Path=LastName}" />
<CheckBox Grid.Column="4"
Content="Is Lecturer?"
IsEnabled="False"
IsChecked="{Binding Path=IsLecturer}" />
</Grid>
</DataTemplate>
</Window.Resources>
<StackPanel>
<ListBox ItemsSource="{Binding}"
ItemTemplate="{StaticResource MyDataTemplate}"
HorizontalContentAlignment="Stretch" />
<Button Content="Add"
Click="Button_Click" />
</StackPanel>
</Window>
and the code Behind
using System.Collections.ObjectModel;
using System.Windows;
namespace CollectionDemo
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private ObservableCollection<MyData> _myCollection =
new ObservableCollection<MyData>();
public MainWindow()
{
InitializeComponent();
DataContext = _myCollection;
_myCollection.Add(
new MyData
{
FirstName = "Arik",
LastName = "Poznanski",
IsLecturer = true
});
_myCollection.Add(
new MyData
{
FirstName = "John",
LastName = "Smith",
IsLecturer = false
});
}
private int counter = 0;
private void Button_Click(object sender, RoutedEventArgs e)
{
++counter;
_myCollection.Add(
new MyData()
{
FirstName = "item " + counter,
LastName = "item " + counter,
IsLecturer = counter % 3 == 0
});
}
}
}
class my data form the example
public class MyData
{
public string User { get; set; }
public string Password { get; set; }
}
I made a custom example which matches your scenario, take a look at this.
MainWindow.xaml
<Window x:Class="SO.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<TextBlock Height="30" Text="{Binding Parent.Child.SampleText}" HorizontalAlignment="Center"/>
</Grid>
</Window>
MainWindow.xaml.cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
MainViewModel obj = new MainViewModel();
this.DataContext = obj;
}
}
MainViewModel.cs
public class MainViewModel
{
private ParentModel _Parent = new ParentModel();
public ParentModel Parent
{
get { return _Parent; }
set { _Parent = value; }
}
public MainViewModel() //Data Load in Constructor
{
ChildModel child = new ChildModel();
child.SampleText = "Hi, I am Child!";
Parent.Child = child;
}
}
ParentModel.cs
public class ParentModel
{
private ChildModel _Child = new ChildModel();
public ChildModel Child
{
get { return _Child; }
set { _Child = value; }
}
}
ChildModel.cs
public class ChildModel
{
private string _SampleText ;
public string SampleText
{
get { return _SampleText; }
set { _SampleText = value; }
}
}
Corrections in your eg:
Your View and Code behind is perfect.
You didn't add properties in model class which is to be binded in UI.
class MyData
{
//public string User { get; set; }
//public string Password { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public bool IsLecturer { get; set; }
}

WPF MVVM Data Binding

Im trying to implement the MVVM Pattern i just want to have a TextBox that shows some initial text at startup.
this is my view: (dont care about the buttons and the listbox for now)
<Window x:Class="Friends.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBox Grid.Row="0" Width="150" Text="{Binding Friend}"></TextBox>
<ListBox Grid.Row="1" Width="150"></ListBox>
<Button Grid.Row="2" Content="Previous" Width="150"></Button>
<Button Grid.Row="3" Content="Next" Width="150"></Button>
</Grid>
this is my model:
public class FriendsModel : INotifyPropertyChanged
{
private string _firstName;
public string FirstName
{
get { return _firstName; }
set
{
_firstName = value;
RaisePropertyChanged("FirstName");
}
}
public FriendsModel(string _initialName)
{
_firstName = _initialName;
}
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string _newName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) {
handler(this, new PropertyChangedEventArgs(_newName));
}
}
}
and this is my viewmodel:
public class FriendsViewModel
{
public FriendsModel Friend { get; set; }
public FriendsViewModel()
{
Friend = new FriendsModel("Paul");
}
}
in the code behind i have:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new FriendsViewModel();
}
}
my project is building without any errors but it doesnt show the text in my textbox. Can anyone help me?
thanks in advance
edit:
i changed it to
<TextBox Grid.Row="0" Width="150" Text="{Binding Friend.Firstname}"></TextBox>
its still not working.
The binding should point the FirstName property. WPF can not figure out by him self how to convert Friend class to string.
Text="{Binding Friend.FirstName}"
the Friend in the binding represents the full object, you must specify the membre...
try to replace{Binding Friend} by {Binding Friend.FirstName}
The DataContext is being set right after InitializeComponent() is called, this means that the bindings have already been setup, the textbox is correctly binding to the FirstName property but at the point of binding it's empty.
if you want the textbox to update when the property does you'll need to set DataContext before InitializeComponent()
public MainWindow()
{
DataContext = new FriendsViewModel();
InitializeComponent();
}
gives the result
Have you tried this:
public FriendsModel(string _initialName)
{
this.FirstName = _initialName;
}
Regards,

Binding Textbox to Two sources WPF

I have a text box, which default value I want to bind to Combo box selecteItem, and same time I want my text box to be binded to Mvvm object property?
I checked here but the multibinding confuse me.
I would prefer to have xaml solution for this issue.
Addition:
In combobox I will select an Account, that account contain some values (Amount), I want to display Amount, But need my text box to be bounded to mvvm model object element stAmount. so the user can change the amount selected by combobbox and then this modified or unchanged amount value could be stored to text box binded model-object element (stAmount)
Making use of INotifyPropertyChanged:
XAML
<Window x:Class="INotifyPropertyChangedExample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Title="INotifyPropertyChanged Example" Width="380" Height="100">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Label Content="Account Name:" />
<Label Grid.Row="1" Grid.Column="0" Content="Account Balance:" />
<ComboBox Grid.Row="0" Grid.Column="1" Width="200" Height="25" ItemsSource="{Binding AccountsCollection}" SelectedItem="{Binding SelectedAccount}" DisplayMemberPath="Name" />
<TextBox Grid.Column="1" Grid.Row="1" Width="200" Height="25" Text="{Binding SelectedAccount.Balance}" />
</Grid>
</Window>
C#
namespace INotifyPropertyChangedExample
{
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
public partial class MainWindow : Window, INotifyPropertyChanged
{
private ObservableCollection<Account> acctountsCollection;
public ObservableCollection<Account> AccountsCollection
{
get
{
return this.acctountsCollection;
}
set
{
this.acctountsCollection = value;
OnPropertyChanged();
}
}
private Account selectedAccount;
public Account SelectedAccount
{
get
{
return this.selectedAccount;
}
set
{
this.selectedAccount = value;
OnPropertyChanged();
}
}
public MainWindow()
{
InitializeComponent();
this.AccountsCollection = new ObservableCollection<Account>()
{
new Account { Id = 1, Name = "My super account", Balance = 123.45 },
new Account { Id = 2, Name = "My super account 2", Balance = 543.21 },
};
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
public class Account
{
public int Id { get; set; }
public string Name { get; set; }
public double Balance { get; set; }
}
}
In this example we bind an ObservableCollection of Account objects to your ComboBox and keep track of which Account is selected through the SelectedItem property. We bind the TextBox text property to the Balance property of the selected Account object. Therefore when then selected Account object changes the value displayed in the TextBox changes to reflect the Balance of the Account.
Additionally if you change the value in the TextBox, the Balance value of the Account object is updated.
It seems to me like you want bind your textbox to the selected value property in your viewmodel not the combo box.
using System.Collections.ObjectModel;
using System.Windows;
namespace WpfApplication1
{
public partial class MainWindow : Window
{
public ObservableCollection<string> Items
{
get { return (ObservableCollection<string>)GetValue(ItemsProperty); }
set { SetValue(ItemsProperty, value); }
}
public static readonly DependencyProperty ItemsProperty =
DependencyProperty.Register("Items", typeof(ObservableCollection<string>), typeof(MainWindow), new PropertyMetadata(null));
public string SelectedValue
{
get { return (string)GetValue(SelectedValueProperty); }
set { SetValue(SelectedValueProperty, value); }
}
public static readonly DependencyProperty SelectedValueProperty =
DependencyProperty.Register("SelectedValue", typeof(string), typeof(MainWindow), new PropertyMetadata(null));
public MainWindow()
{
InitializeComponent();
Items = new ObservableCollection<string>();
Items.Add("Value 1");
Items.Add("Value 2");
Items.Add("Value 3");
Items.Add("Value 4");
Items.Add("Value 5");
Items.Add("Value 6");
}
}
}
and 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"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Title="MainWindow" Height="350" Width="525">
<Grid >
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<ComboBox Grid.Row="0" ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedValue}"/>
<TextBox Grid.Row="1" Text="{Binding SelectedValue}"/>
</Grid>
</Window>

Resources