I have the following "element":
public class ReportElementViewModel
{
public string Name
{
get { return _name; }
set
{
if (_name != value)
{
_name = value;
RaisePropertyChanged("Name");
}
}
}
public bool IsChecked
{
get { return _isChecked; }
set
{
if (_isChecked != value)
{
_isChecked = value;
RaisePropertyChanged("IsChecked");
}
}
}
}
My ViewModel contains many ReportElementViewModels:
public abstract class ReportViewModel<TPrimaryModel> : SharedViewModel
where TPrimaryModel : Model, new()
{
public ObservableCollection<ReportElementViewModel> ReportElementViewModels
{
get { return _reportElementViewModels; }
set
{
if (_reportElementViewModels != value)
{
_reportElementViewModels = value;
RaisePropertyChanged("ReportElementViewModels");
}
}
}
}
I removed the members to reduce code complexity but they are implemented correctly.
In my view I want to show all ReportElementViewModels by showing their Name and IsChecked (checkbox).
I thought the ItemsControl would be the right "tool", however it doesn't work (nothing is shown):
<ItemsControl ItemsSource="{Binding ReportElemetViewModels}" Height="auto" VerticalAlignment="Top" Grid.Row="1">
<ItemsControl.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Name}" IsChecked="{Binding IsChecked}" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="269"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
You have made a spelling mistake in your Binding.
ItemsSource="{Binding ReportElemetViewModels}"
Should be:
ItemsSource="{Binding ReportElementViewModels}"
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 information that was gathered from a service about TFS builds put into ViewModels.
Here are the models:
public class Collection : ViewModel
{
private string _name = string.Empty;
public string Name
{
get { return _name; }
set
{
_name = value;
OnPropertyChanged(() => Name);
}
}
private ObservableCollection<Project> _projects = new ObservableCollection<TFSProject>();
public ObservableCollection<Project> Projects
{
get { return _projects; }
set
{
_projects = value;
OnPropertyChanged(() => Projects);
}
}
}
public class Project : ViewModel
{
private string _name = string.Empty;
public string Name
{
get { return _name; }
set
{
_name = value;
OnPropertyChanged(() => Name);
}
}
private ObservableCollection<string> _buildDefinitions = new ObservableCollection<string>();
public ObservableCollection<string> BuildDefinitions
{
get { return _buildDefinitions; }
set
{
_buildDefinitions = value;
OnPropertyChanged(() => BuildDefinitions);
}
}
}
I am binding my combobox's itemssource to a ObservableCollection<Collection>. The problem is that the collection, project, and build definition names are stored in a class that defines them as separate string properties:
public class BuildMonitor : INotifyPropertyChanged
{
[Description("In TFS, each team project exists within a TFS Collection. This is the name of the collection applicable to the build that this monitor is for. Default='Vision2010'")]
public string Collection
{
get { return collection_; }
set
{
collection_ = value;
OnPropertyChanged(() => Collection);
}
}
private string collection_ = "Vision2010";
[Description("BuildDefintions reside within a TeamProject. This is the name of the TeamProject where the build definition this monitor is for resides. Default='Double-Take2010'")]
public string TeamProject { get { return teamProject_; } set { teamProject_ = value; OnPropertyChanged(() => TeamProject); } }
private string teamProject_ = "Double-Take2010";
[Description("Builds are defined in TFS as the execution of a particular BuildDefinition. This is the name of the build defintion (thus; the build) this monitor is for.")]
public string BuildDefinition { get { return buildDefinition_; } set { buildDefinition_ = value; OnPropertyChanged(() => BuildDefinition); } }
private string buildDefinition_;
[Description("Used only if this monitor should watch for builds specified by a particular user. Enter the domain name of the user, or leave blank to monitor builds by any user.")]
public string RequestedByFilter { get { return requestedByFilter_; } set { requestedByFilter_ = value; OnPropertyChanged(() => RequestedByFilter); } }
private string requestedByFilter_;
[Description("The command to execute when the build monitor is triggered.")]
public string Command { get { return command_; } set { command_ = value; OnPropertyChanged(() => Command); } }
private string command_;
[Description("The arguments to pass to the command. Arguments will resolve known build monitor macros.")]
public string Arguments { get { return arguments_; } set { arguments_ = value; OnPropertyChanged(() => Arguments); } }
private string arguments_;
[Description("If TRUE, the monitor will fire only once, at which point it will be marked as 'invalid' and never fire again.")]
public bool RunOnce { get { return runOnce_; } set { runOnce_ = value; OnPropertyChanged(() => RunOnce); } }
private bool runOnce_ = false;
[Description("The maximum age (in hours) a build can be (since finished), for the monitor to consider it for processing. Default='0'")]
public int MaxAgeInHours { get { return maxAgeInHours_; } set { maxAgeInHours_ = value; OnPropertyChanged(() => MaxAgeInHours); } }
private int maxAgeInHours_ = 0;
[Description("Which status trigger the monitor should 'fire' on. When the build status matches this trigger, the monitor command will be executed. Default='Succeeded'")]
public BuildStatus EventTrigger { get { return eventTrigger_; } set { eventTrigger_ = value; OnPropertyChanged(() => EventTrigger); } }
private BuildStatus eventTrigger_ = BuildStatus.Succeeded;
[Browsable(false), Description("Used internally to reliably compare two BuildMonitors against each other.")]
public Guid ID { get { return id_; } set { id_ = value; } }
private Guid id_ = Guid.NewGuid();
[Browsable(false), Description("Used internally to determine if the monitor is still valid/should be processed.")]
public bool IsEnabled { get { return isEnabled_; } set { isEnabled_ = value; } }
private bool isEnabled_ = true;
[Browsable(false), XmlIgnore, Description("Used internally to track when the monitor is 'busy' (currently running the 'Command' selected.")]
public int CurrentProcessID { get { return currentProcessID_; } set { currentProcessID_ = value; } }
private int currentProcessID_ = 0;
[Browsable(false), XmlIgnore, Description("Used internally to track the build that the monitor is currently processing.")]
private string currentBuildUri_;
public string CurrentBuildUri { get { return currentBuildUri_; } set { currentBuildUri_ = value; } }
[field: NonSerialized, Browsable(false)]
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged<T>(Expression<Func<T>> propertyExpression)
{
MemberExpression memberExpression = (MemberExpression)propertyExpression.Body;
string propertyName = memberExpression.Member.Name;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
In my xaml I have attempted to represent the selection of this data by setting the itemssource of the collection combobbox to a relative source binding which is the ObservableCollection<Collection>. I get the items in the list ok but since the itemssource is a List<BuildMonitors>, I can't seem to get the selected item to map over the name property of the selected item to the actual binding of the data item (string Collection in the BuildMonitor instance).
<tk:DataGrid ItemsSource="{Binding Monitors}"
AutoGenerateColumns="False">
<tk:DataGrid.Columns>
<tk:DataGridTemplateColumn Header="Collection">
<tk:DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox x:Name="Collection"
ItemsSource="{Binding Path=AllCollections, RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type apollo:BuildMonitorNew}}}"
DisplayMemberPath="Name"
SelectedItem="{Binding .}"
SelectedValuePath="Collection"
SelectedValue="{Binding Name}"/>
</DataTemplate>
</tk:DataGridTemplateColumn.CellEditingTemplate>
<tk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Collection,Mode=TwoWay}"/>
</DataTemplate>
</tk:DataGridTemplateColumn.CellTemplate>
</tk:DataGridTemplateColumn>
<tk:DataGridTemplateColumn Header="Project">
<tk:DataGridTemplateColumn.CellEditingTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding ElementName=Collection,Path=SelectedItem.Projects}">
<ComboBox x:Name="Projects"
ItemsSource="{Binding}"
DisplayMemberPath="Name"/>
</HierarchicalDataTemplate>
</tk:DataGridTemplateColumn.CellEditingTemplate>
</tk:DataGridTemplateColumn>
<tk:DataGridTextColumn Binding="{Binding Command}"
Header="Command"/>
<tk:DataGridTextColumn Binding="{Binding Arguments}"
Header="Arguments"
Width="*"/>
</tk:DataGrid.Columns>
My first thought is that although my viewmodel may be a better representation of the data (hierarchical), the structure of the data to select vs the data to actual store is too different.
I would love to be wrong here and find a snazzy way to convert the data that is actually selected(Collection,Project, and then BuildDefinition) to the path of the data that is stored (BuildMonitor).
Any ideas?
I found that the multivalue converter allowed me to transform the hierarchical structure into parts for the combobox item source where they are representing a list.
Converter:
public class BuildMonitorItemSource : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (values.Count() == 2)
{
string collectionToGet = parameter.ToString();
ObservableCollection<TFSCollection> allcollections = values[1] as ObservableCollection<TFSCollection>;
BuildLauncher.BuildMonitor currentBM = (values[0] as BuildLauncher.BuildMonitor);
if (collectionToGet.Equals("Projects"))
{
return allcollections.FirstOrDefault(x => x.Name.Equals(currentBM.Collection, StringComparison.OrdinalIgnoreCase)).Projects;
}
else if (collectionToGet.Equals("BuildDefinitions"))
{
TFSCollection currentCollection = allcollections.FirstOrDefault(x => x.Name.Equals(currentBM.Collection));
TFSProject currentProject = currentCollection.Projects.FirstOrDefault(x => x.Name.Equals(currentBM.TeamProject));
return currentProject.BuildDefinitions;
}
}
return values;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
This is the modified xml:
<tk:DataGrid ItemsSource="{Binding Monitors}"
AutoGenerateColumns="False"
IsEnabled="{Binding RelativeSource={RelativeSource AncestorType=apollo:BuildMonitorNew}, Path=TFSAuthenticated}"
Name="MontiorsGrid">
<tk:DataGrid.Columns>
<tk:DataGridCheckBoxColumn Binding="{Binding IsEnabled}">
<tk:DataGridCheckBoxColumn.Header>
<Ellipse Grid.Column="0"
HorizontalAlignment="Left"
Height="10" Width="10"
Stroke="Black"
StrokeThickness="1"
Fill="Green"/>
</tk:DataGridCheckBoxColumn.Header>
</tk:DataGridCheckBoxColumn>
<tk:DataGridTemplateColumn Header="Collection">
<tk:DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox x:Name="CollectionCombo"
ItemsSource="{Binding Path=AllCollections, RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type apollo:BuildMonitorNew}}}"
DisplayMemberPath="Name"
SelectedValue="{Binding Collection}"
SelectedValuePath="Name">
</ComboBox>
</DataTemplate>
</tk:DataGridTemplateColumn.CellEditingTemplate>
<tk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Collection,Mode=TwoWay}"/>
</DataTemplate>
</tk:DataGridTemplateColumn.CellTemplate>
</tk:DataGridTemplateColumn>
<tk:DataGridTemplateColumn Header="Project">
<tk:DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox x:Name="Projects"
DisplayMemberPath="Name"
SelectedValue="{Binding TeamProject}"
SelectedValuePath="Name">
<ComboBox.ItemsSource>
<MultiBinding Converter="{StaticResource GetItemSource}" ConverterParameter="Projects" >
<Binding Path="." />
<Binding Path="AllCollections" RelativeSource="{RelativeSource Mode=FindAncestor,AncestorType={x:Type apollo:BuildMonitorNew}}"/>
</MultiBinding>
</ComboBox.ItemsSource>
</ComboBox>
</DataTemplate>
</tk:DataGridTemplateColumn.CellEditingTemplate>
<tk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding TeamProject,Mode=TwoWay}"/>
</DataTemplate>
</tk:DataGridTemplateColumn.CellTemplate>
</tk:DataGridTemplateColumn>
<tk:DataGridTemplateColumn Header="Build Definition">
<tk:DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox SelectedItem="{Binding BuildDefinition}">
<ComboBox.ItemsSource>
<MultiBinding Converter="{StaticResource GetItemSource}" ConverterParameter="BuildDefinitions">
<Binding Path="." />
<Binding Path="AllCollections" RelativeSource="{RelativeSource Mode=FindAncestor,AncestorType={x:Type apollo:BuildMonitorNew}}"/>
</MultiBinding>
</ComboBox.ItemsSource>
</ComboBox>
</DataTemplate>
</tk:DataGridTemplateColumn.CellEditingTemplate>
<tk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding BuildDefinition,Mode=TwoWay}"/>
</DataTemplate>
</tk:DataGridTemplateColumn.CellTemplate>
</tk:DataGridTemplateColumn>
<tk:DataGridTextColumn Binding="{Binding Command}"
Header="Command"/>
<tk:DataGridTextColumn Binding="{Binding Arguments}"
Header="Arguments"
Width="*"/>
</tk:DataGrid.Columns>
</tk:DataGrid>
I have a TextBox, its Text property is bound to a property of type double named Grade. I also have a CheckBox, when the CheckBox is checked I want the Grade to take an auto calculated value (i.e. automatically set to MaxScore/Count of questions). If the CheckBox is not checked then I want to set and change the Grade Manually. My question is how can I implement this?
<TextBox Height="23"
Visibility="{Binding Path=Visible2, Converter={StaticResource boolToVis}, UpdateSourceTrigger=PropertyChanged}"
Text="{Binding Path=Grade,UpdateSourceTrigger =PropertyChanged,Mode=TwoWay}"
HorizontalAlignment="Left" Margin="376,453,0,0"
Name="textBox3" VerticalAlignment="Top" Width="120" />
and i bind this to:
public double Grade
{
get
{
return grade;
}
set
{
grade = value;
OnPropertyChanged("Grade");
foreach (ExaminationQuestion exaq in
this.Examination.ExaminationQuestions)
{
if (exaq.Question.Guid == SelectedQuestionDropList.Guid)
{
exaq.Grade = value;
}
}
}
}
Thanks
in your VM, have another public Property Auto and make sure your Checkbox binds to it and so does your TextBox (so that it becomes readonly/disabled/hidden). And my default AutoCheck will be true
<StackPanel Orientation="Horizontal" VerticalAlignment="Top">
<Label Content="Grade" />
<TextBox Height="23" Width="120"
Text="{Binding Path=GradeDisplay}"
IsEnabled="{Binding EnableBox}"
/>
<Label Content="Auto?" />
<CheckBox IsChecked="{Binding IsAuto}" />
</StackPanel>
And for the View Model
public bool EnableBox { get; set; }
public string GradeDisplay
{
get
{
if (EnableBox)
return Grade.ToString();
else
return "AUTO";
}
set
{
double result;
if (double.TryParse(value, out result))
Grade = result;
NotifyPropertyChanged("GradeDisplay");
}
}
private bool _IsAuto;
public bool IsAuto
{
get
{
return _IsAuto;
}
set
{
_IsAuto = value;
EnableBox = !value;
NotifyPropertyChanged("GradeDisplay");
NotifyPropertyChanged("EnableBox");
}
}
private double _Grade;
private double Grade
{
set
{
_Grade = value;
}
get
{
if (IsAuto)
{
// CODE TO GET AUTO GRADE
return 0.0;
}
else
{ // RETURN MANUALLY SET GRADE
return _Grade;
}
}
}
// CTOR
public MainWindowViewModel()
{
IsAuto = false;
}
Ive posted another thread regarding refreshing a silverlight listbox - In the meantime Ive become slightly more familiar with the issue. It has to do with implementing the ObservableCollection interface.
Im using RIA services to populate a listbox with a collection of type ObservableCollection. The problem is refreshing the Items once the database has been updated. I am using a silverlight child window to save the data to the database, and this is happening correctly On the close event of the child window.
Can anyone give me more information as to why the ListBox is not updating.
Thanks
You need to make your poco class that is used within your ObservableCollection implement INotifyChanged.
Example:
<viewModels:LocationsViewModel x:Key="viewModel" />
.
.
.
<ListView
DataContext="{StaticResource viewModel}"
ItemsSource="{Binding Locations}"
IsItemClickEnabled="True"
ItemClick="GroupSection_ItemClick"
ContinuumNavigationTransitionInfo.ExitElementContainer="True">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" Margin="0,0,10,0" Style="{ThemeResource ListViewItemTextBlockStyle}" />
<TextBlock Text="{Binding Latitude, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Style="{ThemeResource ListViewItemTextBlockStyle}" Margin="0,0,5,0"/>
<TextBlock Text="{Binding Longitude, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Style="{ThemeResource ListViewItemTextBlockStyle}" Margin="5,0,0,0" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
public class LocationViewModel : BaseViewModel
{
ObservableCollection<Location> _locations = new ObservableCollection<Location>();
public ObservableCollection<Location> Locations
{
get
{
return _locations;
}
set
{
if (_locations != value)
{
_locations = value;
OnNotifyPropertyChanged();
}
}
}
}
public class Location : BaseViewModel
{
int _locationId = 0;
public int LocationId
{
get
{
return _locationId;
}
set
{
if (_locationId != value)
{
_locationId = value;
OnNotifyPropertyChanged();
}
}
}
string _name = null;
public string Name
{
get
{
return _name;
}
set
{
if (_name != value)
{
_name = value;
OnNotifyPropertyChanged();
}
}
}
float _latitude = 0;
public float Latitude
{
get
{
return _latitude;
}
set
{
if (_latitude != value)
{
_latitude = value;
OnNotifyPropertyChanged();
}
}
}
float _longitude = 0;
public float Longitude
{
get
{
return _longitude;
}
set
{
if (_longitude != value)
{
_longitude = value;
OnNotifyPropertyChanged();
}
}
}
}
public class BaseViewModel : INotifyPropertyChanged
{
#region Events
public event PropertyChangedEventHandler PropertyChanged;
#endregion
protected void OnNotifyPropertyChanged([CallerMemberName] string memberName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(memberName));
}
}
}
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);