I need some help with binding. Twoway mode doesn't work at all.
I fill my window with data passed to the constructor and it's working fine.
The problem is that I can't rewrite some data imputed in the window control even if I use Twoway binding.
Below is how I open window
var tempInregistrare = BaseConnection.GetInregistrareById(itemSelected.InregistrareId.ToString());
var tichet = new TichetView(new InregistrareModel {
Id =tempInregistrare.Id,
NumeFurnizor = tempInregistrare.NumeFurnizor,
IdFurnizor = tempInregistrare.IdFurnizor,
NumeProdus = tempInregistrare.NumeProdus......
ticket.Show();
Here is window constructor with DataContext set to self.
public TichetView(InregistrareModel inregistrare)
{
InitializeComponent();
InregistrareModel = inregistrare;
DataContext = this;
grdButtonsPrint.Visibility = Visibility.Visible;
}
public InregistrareModel InregistrareModel
{
get => inregistrareModel;
set
{
if (value != inregistrareModel)
{
inregistrareModel = value;
NotifyPropertyChanged();
}
}
}
public class InregistrareModel
{
public int Id { get; set; }
public int IdProdus { get; set; }
public int IdFurnizor { get; set; }
public string NumeProdus { get; set; }
public string NumeFurnizor { get; set; }
public string NrAuto { get; set; }
public string NumeSofer { get; set; }
public double CantitateInitiala { get; set; }
public double CantitateIesire { get; set; }
public double Umiditate { get; set; }
public double CantitateScazuta { get; set; }
public double CantitateMarfa { get; set; }
public DateTime DataIntrare { get; set; }
public DateTime DataIesire { get; set; }
public FurnizorModel Furnizor { get; set; }
public int NIR { get; set; }
}
And here is Xaml of window
<TextBlock Grid.Row="2" Grid.Column="2" VerticalAlignment="Center">Intrare</TextBlock>
<TextBox Grid.Row="2" Grid.Column="3" Text="{Binding InregistrareModel.CantitateInitiala}"/>
<TextBlock Grid.Row="4" Grid.Column="2" VerticalAlignment="Center">Umiditatea (%)</TextBlock>
<TextBox x:Name="txtUmiditate" Grid.Row="4" Grid.Column="3" IsReadOnly="False" Text="{Binding InregistrareModel.Umiditate, Mode=TwoWay}"/>
<TextBlock Grid.Row="5" Grid.Column="2" VerticalAlignment="Center">Cantitatea scazuta</TextBlock>
<TextBox x:Name="txtCantitateScazuta" Grid.Row="5" Grid.Column="3" IsReadOnly="False" Text="{Binding InregistrareModel.CantitateScazuta, Mode=TwoWay}"/>
<TextBlock Grid.Row="6" Grid.Column="2" VerticalAlignment="Center">Iesire</TextBlock>
<TextBox Grid.Row="6" Grid.Column="3" Text="{Binding InregistrareModel.CantitateIesire}"/>
<TextBlock Grid.Row="7" Grid.Column="2" VerticalAlignment="Center">Dată iesire</TextBlock>
<TextBox Grid.Row="7" Grid.Column="3" Text="{Binding InregistrareModel.DataIesire,StringFormat='{}{0:HH:HH dd/M/yyyy}'}"/>
<TextBlock Grid.Row="10" Grid.Column="2" VerticalAlignment="Center">Net</TextBlock>
<TextBox Grid.Row="10" Grid.Column="3" Text="{Binding InregistrareModel.CantitateMarfa}"/>
All text boxes are filled with data expect the second and third that I fill by hand.
The goal that I can't achieve right now is to take data from 1st textbox(InregistrareModel.CantitateInitiala) to type in 3rd(txtCantitateScazuta) some data and show the result in the last textbox so after I update my database with this data.
I totally agree with #Peter Boone.
You have a lot of gross architectural mistakes in the Solution and for good reason it needs to be completely redone.
But if you do not have such an opportunity, try to implement this option.
For fields (TextBox, TextBlock) that change, declare properties in the Window.
In the body of these properties, implement communication with the parent container (InregistrareModel) and with other properties.
Let's say you have a CantitateInitiala property that affects the value of the CantitateScazuta property.
public InregistrareModel InregistrareModel
{
get => inregistrareModel;
set
{
if (value != inregistrareModel)
{
inregistrareModel = value;
NotifyPropertyChanged();
CantitateInitiala = InregistrareModel.CantitateInitiala;
}
}
public double CantitateInitiala
{
get => InregistrareModel.CantitateInitiala;
set
{
if (value != InregistrareModel.CantitateInitiala)
{
InregistrareModel.CantitateInitiala = value;
NotifyPropertyChanged();
// Calculation of the CantitateScazuta value
double cantSc = CantitateInitiala / 123.45;
CantitateScazuta = cantSc;
}
}
}
public double CantitateScazuta
{
get => InregistrareModel.CantitateScazuta;
set
{
if (value != InregistrareModel.CantitateScazuta)
{
InregistrareModel.CantitateScazuta = value;
NotifyPropertyChanged();
}
}
}
In XAML, change the bindings for these fields:
<TextBlock Grid.Row="2" Grid.Column="2" VerticalAlignment="Center">Intrare</TextBlock>
<TextBox Grid.Row="2" Grid.Column="3" Text="{Binding CantitateInitiala}"/>
<TextBlock Grid.Row="4" Grid.Column="2" VerticalAlignment="Center">Umiditatea (%)</TextBlock>
<TextBox x:Name="txtUmiditate" Grid.Row="4" Grid.Column="3" IsReadOnly="False" Text="{Binding InregistrareModel.Umiditate, Mode=TwoWay}"/>
<TextBlock Grid.Row="5" Grid.Column="2" VerticalAlignment="Center">Cantitatea scazuta</TextBlock>
<TextBox x:Name="txtCantitateScazuta" Grid.Row="5" Grid.Column="3" IsReadOnly="False" Text="{Binding CantitateScazuta, Mode=TwoWay}"/>
Но нужно тщательно продумать алгоритм зависимостей свойств в том случае, если они имеют циклическую зависимость.
То есть не только изменение CantitateInitiala влияет на значение CantitateScazuta, но также существует обратная зависимость CantitateInitiala от изменения CantitateScazuta.
You should make the ViewModel a separate file/class. Let's call it TichetViewModel. This class should have the InregistrareModel. Something like this:
public class TichetViewModel : ObservableObject
{
private InregistrareModel _InregistrareModel;
public InregistrareModel InregistrareModel
{
get { return _InregistrareModel; }
set
{
if (value != _InregistrareModel)
{
_InregistrareModel = value;
NotifyPropertyChanged();
}
}
}
public TichetViewModel()
{
InregistrareModel = new InregistrareModel();
}
}
Then set the DataContext of TichetView in either you code behind or in xaml.
Code behind:
TichetView.xaml.cs
public TichetView()
{
InitializeComponent();
DataContext = new TichetViewModel();
}
or in xaml
TichetView.xaml
<Window.DataContext>
<local:TichetViewModel />
</Window.DataContext>
I like doing this in xaml because the Intellisense in Visual Studio picks this up and autocompletes based on the classes.
Implement INotifyPropertyChanged on the properties of the InregistrareModel. Like this:
public class InregistrareModel : ObservableObject
{
private int _Id;
public int Id
{
get { return _Id; }
set
{
if (value != _Id)
{
_Id = value;
NotifyPropertyChanged();
}
}
}
private string _NumeProdus;
public string NumeProdus
{
get { return _NumeProdus; }
set
{
if (value != _NumeProdus)
{
_NumeProdus = value;
NotifyPropertyChanged();
}
}
}
}
Related
I am trying to realize Wordle(Game) in WPF as a project to practice. In the ViewModel I have a Property(e.g. FirstWord) for the first, second, third, fourth and fifth word, all of which have INotifyPropertyChanged implemented. I would like to avoid creating a property for every single textbox (would be 5x5). Therefore, my model consists of 1st letter, 2nd letter, 3rd letter, etc. In XAML the binding looks like this: {Binding FirstWord.FirstLetter, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}.
When debugging, the program does not even jump into the setter, it was not detected that the value has changed. What can be the reason for this?
ViewModel
public class WordleViewModel : ObservableObject
{
private int counter;
public string solutionWord;
private static int[] _stateColor = new int[5];
public static int[] StateColor
{
get { return _stateColor;} private set { _stateColor = value; }
}
private SafeWordsModel _firstWord;
public SafeWordsModel FirstWord
{
get { return _firstWord; }
set
{
_firstWord = value;
OnPropertyChanged();
}
}
//....
public WordleViewModel()
{
solutionWord = "TESTE";
}
}
Model (Do I really need variable + Property and the INotifyChanged here?)
public class SafeWordsModel : ObservableObject
{
private string _firstLetter;
private string _secondLetter;
private string _thirdLetter;
private string _fourthLetter;
private string _fifthLetter;
public string FirstLetter
{
get { return _firstLetter; }
set { _firstLetter = value; OnPropertyChanged(); }
}
public string SecondLetter
{
get { return _secondLetter; }
set { _secondLetter = value; OnPropertyChanged(); }
}
public string ThirdLetter
{
get { return _thirdLetter; }
set { _thirdLetter = value; OnPropertyChanged(); }
}
public string FourthLetter
{
get { return _fourthLetter; }
set { _fourthLetter = value; OnPropertyChanged(); }
}
public string FifthLetter
{
get { return _fifthLetter; }
set { _fifthLetter = value; OnPropertyChanged(); }
}
public SafeWordsModel()
{
this.FirstLetter = _firstLetter;
this.SecondLetter = _secondLetter;
this.ThirdLetter = _thirdLetter;
this.FourthLetter = _fourthLetter;
this.FifthLetter = _fifthLetter;
}
}
View
public WordleView()
{
InitializeComponent();
ViewModel = new WordleViewModel();
}
public WordleViewModel ViewModel
{
get { return DataContext as WordleViewModel; }
set { DataContext = value; }
}
public void FocusNext(object sender, TextChangedEventArgs e)
{
if (((TextBox)sender).MaxLength == ((TextBox)sender).Text.Length)
{
// move focus
var ue = e.OriginalSource as FrameworkElement;
e.Handled = true;
ue.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
}
}
XAML for one Word
<StackPanel Orientation="Horizontal"
FocusManager.FocusedElement="{Binding ElementName=tbx11}">
<TextBox x:Name="tbx11"
Style="{StaticResource Input_tbx}"
TextChanged="FocusNext"
Background="{Binding ElementName=Line2_ckb, Path=IsChecked, Converter={StaticResource brush1}}"
Text="{Binding FirstWord.FirstLetter, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<TextBox x:Name="tbx12"
Style="{StaticResource Input_tbx}"
TextChanged="FocusNext"
Background="{Binding ElementName=Line2_ckb, Path=IsChecked, Converter={StaticResource brush2}}"
Text="{Binding FirstWord.SecondLetter, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<TextBox x:Name="tbx13"
Style="{StaticResource Input_tbx}"
TextChanged="FocusNext"
Text="{Binding FirstWord.ThirdLetter, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<TextBox x:Name="tbx14"
Style="{StaticResource Input_tbx}"
TextChanged="FocusNext"
Background="{Binding ElementName=Line2_ckb, Path=IsChecked, Converter={StaticResource brush4}}"
Text="{Binding FirstWord.FourthLetter, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<TextBox x:Name="tbx15"
TextChanged="FocusNext"
Style="{StaticResource Input_tbx}"
Background="{Binding ElementName=Line2_ckb, Path=IsChecked, Converter={StaticResource brush5}}"
Text="{Binding FirstWord.FifthLetter, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</StackPanel>
ObservableObject Class
public class ObservableObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string name = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
So far it has always worked well with INotifyPropertyChanged. It should set the value that comes from the textbox accordingly in the property and I can also use this value. Feel free to make suggestions on other places in the code, I'm still very new to WPF.
I have a ListBox control with TypeUsers.When I select some record in Listbox and update Name in TextBox the Name property/textbox return always null. Never take value from TextBox, always null ?
Image description here
This is my code
<ListBox x:Name="LstTypeUsers"
Grid.Row="0" Grid.Column="4"
Width="220" Height="120"
ScrollViewer.VerticalScrollBarVisibility="Visible"
ItemsSource="{Binding TypeUsers}"
DisplayMemberPath="Name">
</ListBox>
<TextBox
Grid.Row="0" Grid.Column="2"
x:Name="txtName"
HorizontalAlignment="Left" Height="23"
TextWrapping="Wrap"
VerticalAlignment="Top" Width="170"
Text="{Binding ElementName=LstTypeUsers, Path=SelectedItem.Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}"
Validation.ErrorTemplate="{x:Null}"/>
<Button
Grid.Column="0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Width="100" Height="30"
Command="{Binding UpdateTypeUserCmd}"
Grid.ColumnSpan="3" Margin="20,90,0,0">
<StackPanel Orientation="Horizontal">
<Image Source="/Images/Save.png" />
<TextBlock Width="55" Height="18" ><Run Text=" "/><Run Text="Update"/></TextBlock>
</StackPanel>
</Button>
EDIT
// Model class
public class UserType: INotifyPropertyChanged
{
[Key]
private int usertypeId;
public int UserTypeId
{
get
{
return this.usertypeId;
}
set
{
this.usertypeId = value;
OnPropertyChanged("UserTypeId");
}
}
[MaxLength(200)]
private string name;
public string Name
{
get
{
return this.name;
}
set
{
this.name = value;
OnPropertyChanged("Name");
}
}
[Required]
private bool status;
public bool Status
{
get
{
return this.status;
}
set
{
this.status = value;
OnPropertyChanged("Status");
}
}
public virtual ObservableCollection<User> User { get; private set; }
public UserType()
{
this.User = new ObservableCollection<User>();
}
}
// ViewModelBase class
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
// UserTypeViewModel
public class UserTypeViewModel
private UserType _userType;
private ObservableCollection<UserType> _UserTypeList;
// Constructor
public UserTypeViewModel()
{
_userType = new UserType();
_UserTypeList = new ObservableCollection<UserType>(GetUserTypeAll());
}
public ObservableCollection<TypeUsers> TypeUsers
{
get
{
return _UserTypeList;
}
set
{
_UserTypeList = value;
//OnPropertyChanged("TypeUsers");
}
}
public string Name
{
get
{
return _userType.Name;
}
set
{
_userType.Name = value;
//OnPropertyChanged("Name");
}
}
Thank you.
Implement INotifyPropertyChanged interface in UserType class.
You're binding directly to the WPF control (ListBox) and not the ViewModel. I suggest you add a property in your ViewModel that will bind to the TextBox.Text property, once the data changes or the user had changed the value in the TextBox, then the data will update and be reflected in the UI.
Also, if I remember correctly, at launch, the SelectedItem property of the ListBox is null, so there might be a problem there too, but I'm not certain about that...
I have resolved my problem. I have also implemented INotifyPropertyChanged interface in Model class. I'm new in WPF MVVM and I read that this interface is implemented only in the ViewModel for connection with View. Now I have implemented in both classes and everything works great.
Thanks Everyone.
I am pretty new to windows phone app development. I am trying to fill a list box but it's not getting populated. I have debugged and saw that View model is returning the data in OnNavigatioTo method but still list box is empty. Can somebody suggest any thing after looking at the code below:
Xaml page
`
<!--TitlePanel contains the name of the application and page title-->
<StackPanel Grid.Row="0" Margin="12,17,0,28">
<TextBlock Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock Text="list box" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<ListBox x:Name="mylistbox" ItemsSource="{Binding Path=Diet}" Margin="0,0,0,101" SelectionChanged="mylistbox_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<!--<Grid Height="80" VerticalAlignment="Top">-->
<TextBlock x:Name="nameblock" Text="{Binding foodName}" HorizontalAlignment="Left" TextWrapping="Wrap" VerticalAlignment="Top" Height="57" Width="236" FontSize="36" Margin="10,10,0,0" />
<!--<Button Content="Edit" HorizontalAlignment="Left" Margin="275,0,0,0" VerticalAlignment="Top" Height="80" Width="181" Click="Button_Click"/>-->
<!--</Grid>-->
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<!--<TextBlock Grid.Column="0" x:Name="txtFoodName" Text="{Binding foodName}" VerticalAlignment="Center"/>-->
<!--<TextBlock x:Name="Studentnameblock" HorizontalAlignment="Left" Margin="40,543,0,0" TextWrapping="Wrap" Text="Student name" VerticalAlignment="Top" Height="64" Width="193" FontSize="30"/>-->
<TextBlock x:Name="marksblock" HorizontalAlignment="Left" Margin="322,543,0,0" TextWrapping="Wrap" Text="Marks" VerticalAlignment="Top" Height="64" Width="134" FontSize="30"/>
</Grid>
</Grid>`
Code behind
public partial class DietEdit : PhoneApplicationPage
{
public DietViewModel ViewModel;
public DietEdit()
{
InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
try
{
ViewModel = DietViewModel.GetDefault();
this.DataContext = ViewModel.GetAllItems();
}
catch (SQLiteException ex)
{
MessageBox.Show("Can't find that item: " + ex.Message);
}
}
Diet Class
public class Diet : ViewModelBase
{
private long mdietid = -1;
public long dietID
{
get { return mdietid; }
set { SetProperty(ref mdietid, value); }
}
private long mmealid = -1;
public long mealID
{
get { return mmealid; }
set { SetProperty(ref mmealid, value); }
}
private string mmealname = string.Empty;
public string mealName
{
get { return mmealname; }
set { if (SetProperty(ref mmealname, value)) IsDirty = true; }
}
private string mfoodname = string.Empty;
public string foodName
{
get { return mfoodname; }
set { if (SetProperty(ref mfoodname, value)) IsDirty = true; }
}
private long mserving = 0;
public long serving
{
get { return mserving; }
set { SetProperty(ref mserving, value); }
}
private long mcalories = 0;
public long calories
{
get { return mcalories; }
set { SetProperty(ref mcalories, value); }
}
private string mcreateddate = DateTime.Today.ToString();
public string createdDate
{
get { return mcreateddate; }
set { SetProperty(ref mcreateddate, value); }
}
private string mupdateddate = DateTime.Today.ToString();
public string updatedDate
{
get { return mupdateddate; }
set { SetProperty(ref mupdateddate, value); }
}
private bool isDirty = false;
public bool IsDirty
{
get { return isDirty; }
set { SetProperty(ref isDirty, value); }
}
internal Diet()
{ }
internal Diet(long dietid, long mealid, string foodname, long serving, long calories, string createddate, string updateddate, string mealmname)
{
this.dietID = dietid;
this.mealID = mealid;
this.foodName = foodname;
this.serving = serving;
this.calories = calories;
this.createdDate = createdDate;
this.updatedDate = updatedDate;
this.mealName = mealmname;
this.isDirty = false;
}
public bool IsNew { get { return dietID < 0; } }
}
Edit: ViewModel.GetAllItems() is actually returning a collection of type Diet. See the image below:
I just can't make the following situation work:
I have a class, with the following implementation:
public class SelectionItem<T> : ViewModelBase where T : Entity
{
private bool? _isSelected;
public bool? IsSelected
{
get { return _isSelected; }
set
{
_isSelected = value;
RaisePropertyChanged("IsSelected");
}
}
public T Item { get; set; }
}
And I have the following property on my ViewModel:
private IEnumerable<SelectionItem<DB_Aux_Pessoas>> _vendedores;
public IEnumerable<SelectionItem<DB_Aux_Pessoas>> Vendedores
{
get
{
return _vendedores;
}
set
{
_vendedores = value;
RaisePropertyChanged("Vendedores");
}
}
Then, in my View, I have the ComboBox:
<ComboBox Margin="3,0,0,0"
Height="23"
Width="200"
ItemsSource="{Binding Vendedores, Mode=TwoWay}"
Grid.Column="1"
Grid.Row="1"
HorizontalAlignment="Left">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding IsSelected, Mode=TwoWay}" />
<TextBlock Text="{Binding Item.NomeRazaoSocial}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
But when I change the CheckBox on the ComboBoxItem, it does not reflect on the property.
The code for DB_Aux_Pessoas is below:
[MetadataTypeAttribute(typeof(DB_Aux_Pessoas.DB_Aux_PessoasMetadata))]
public partial class DB_Aux_Pessoas
{
// This class allows you to attach custom attributes to properties
// of the DB_Aux_Pessoas class.
//
// For example, the following marks the Xyz property as a
// required property and specifies the format for valid values:
// [Required]
// [RegularExpression("[A-Z][A-Za-z0-9]*")]
// [StringLength(32)]
// public string Xyz { get; set; }
internal sealed class DB_Aux_PessoasMetadata
{
// Metadata classes are not meant to be instantiated.
private DB_Aux_PessoasMetadata()
{
}
public Nullable<short> Cliente { get; set; }
public string Id_Numero { get; set; }
public string NomeRazaoSocial { get; set; }
public Nullable<short> Supervisor { get; set; }
public Nullable<short> Vendedor { get; set; }
}
}
What I am doing wrong here?
Tks in advance.
I can't check this right now, but I'm fairly sure the dependency property IsChecked will only accept a binding to a bool and NOT a Nullable<bool>. You might have to do the conversion in your viewmodel and decide which should be the appropriate default for a null value.
This works fine for me. Add an extra property to give you some visual feedback like this:
public class SelectionItem<T> : ViewModelBase
{
private bool? _isSelected;
public bool? IsSelected
{
get { return _isSelected; }
set
{
_isSelected = value;
RaisePropertyChanged("IsSelected");
RaisePropertyChanged("Feedback");
}
}
public string Feedback
{
get
{
if (!this.IsSelected.HasValue)
{
return "null";
}
if (this.IsSelected.Value)
{
return "yes";
}
return "no";
}
}
public T Item { get; set; }
}
And in your xaml, add an extra TextBlock to show the result:
<ComboBox Grid.Column="1"
Grid.Row="1"
Height="23"
Margin="3,0,0,0"
Width="200"
HorizontalAlignment="Left"
ItemsSource="{Binding Vendedores, Mode=TwoWay}">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding IsSelected, Mode=TwoWay}" />
<TextBlock Text="{Binding Item.NomeRazaoSocial}" />
<TextBlock Text="{Binding Feedback}" Margin="5,0,0,0" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
If you see "Yes", "No", "Null" changing as you click the checkboxes, then it's working. Your code worked for me.
public static readonly DependencyProperty IsCheckedProperty = DependencyProperty.RegisterAttached("IsChecked", typeof(bool), typeof(...),
new PropertyMetadata(false, delegate(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
...
}
IsChecked is bool. You can possibly track BindingExpression Error in Output window.
I have a ComboBox which is has an ItemTemplate applied on it and is bind to a List of entity return using linq. I'm using mvvm. It is bind to it successfully but when I set the selected value of it from code at runtime to show the selected value coming from db it doesn't select it. For reference here is my ComboBox xaml.
<DataTemplate x:Key="ManufacturerDataTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Image x:Name="imgManufacturer" Width="25" Height="25"
Source="{Binding Path=ManufacturerImage}" Grid.Column="0"/>
<TextBlock x:Name="txtManufacturer" Grid.Column="1" HorizontalAlignment="Left"
VerticalAlignment="Center" Text="{Binding Path=ManufacturerName}"
Tag="{Binding Path=ManufacturerID}"/>
</Grid>
</DataTemplate>
<ComboBox x:Name="cboManufacturer"
SelectionChanged="cboManufacturer_SelectionChanged"
ItemsSource = "{Binding Path=CurrentManufacturers}"
SelectedValue="{Binding Path=SelectedManufacturer}"
Grid.Column="3" Grid.Row="2" Margin="20,9.25,68,7.75"
ItemTemplate="{StaticResource ManufacturerDataTemplate}" TabIndex="6"/>
Here is my part from code behind from viewModel.
List<tblManufacturer> currentManufacturers
= new List<tblManufacturer>();
tblManufacturer selectedManufacturer = null;
public List<tblManufacturer> CurrentManufacturers
{
get
{
return currentManufacturers;
}
set
{
currentManufacturers = value;
NotifyPropertyChanged("CurrentManufacturers");
}
}
public tblManufacturer SelectedManufacturer
{
get
{
return selectedManufacturer;
}
set
{
selectedManufacturer = currentManufacturers.Where(mm => mm.ManufacturerID == Convert.ToInt32(selectedDevice.tblManufacturer.EntityKey.EntityKeyValues[0].Value)).First();
NotifyPropertyChanged("SelectedManufacturer");
}
}
Here is the sample code snippet:
Xaml for ComboBox:
<ComboBox ItemsSource="{Binding ManufacturerList}" DisplayMemberPath="Name" SelectedValuePath="ID"
SelectedItem="{Binding SelectedManufacturer}"/>
ViewModel code :
public class Manufacturer
{
public int ID { get; set; }
public string Name { get; set; }
}
private List<Manufacturer> _manufactuerlist;
private Manufacturer _selectedManufacturer;
private void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
public Manufacturer SelectedManufacturer
{
get
{
return _selectedManufacturer;
}
set
{
_selectedManufacturer = value;
NotifyPropertyChanged("SelectedManufacturer");
}
}
public List<Manufacturer> ManufacturerList
{
get
{
return _manufactuerlist;
}
set
{
_manufactuerlist = value;
NotifyPropertyChanged("ManufacturerList");
}
}
And finally Set the Selected Manufacturer in your view model like this:
SelectedManufacturer = _manufactuerlist.Find(m => m.ID == 2);