I am new to WPF. I am trying to make a sign up page. In which combobox is present to get the entry of user's gender. I didn't pass the list from ViewModel but I made it by making ComboBoxItem. I need to make the chosen option back to my viewmodel to save everything in database.
SignUp.xml
<ComboBox x:Name="gender" IsEditable="True" Margin="10,30,0,0" Width="100" Text="Select Gender" SelectedItem="{Binding SelectedItemInFilter}">
<sys:String>No Selection</sys:String>
<sys:String>Male</sys:String>
<sys:String>Female</sys:String>
</ComboBox>
The ViewModel is not getting any hit.
ViewModel.cs
private ObservableCollection<UserInfoModel> _gender;
public ObservableCollection<UserInfoModel> Gender
{
get
{
return _gender;
}
set
{
_gender = value;
NotifyPropertyChanged("Persons");
}
}
Related
I have a combobox with the following options: "HardDelete", "SoftDelete", "MoveToDeletedItems"
I want the default selection to match with the following property of an EmailAction object:
public DeleteMode DeleteMode { get; set; }
Here is the line of code I'm using to try to set this:
cmboDelMode.SelectedItem = emailActionInstance.DeleteMode.ToString();
Related XAML:
<ComboBox x:Name="cmboDelMode" HorizontalAlignment="Left" Margin="149,218,0,0" VerticalAlignment="Top" Width="120">
<ComboBoxItem Content="HardDelete" HorizontalAlignment="Left" Width="118"/>
<ComboBoxItem Content="SoftDelete" HorizontalAlignment="Left" Width="118"/>
<ComboBoxItem Content="MoveToDeletedItems" HorizontalAlignment="Left" Width="118"/>
</ComboBox>
Currently the combobox is defaulting to being empty so is not working as expected. I am able to use "emailActionInstance.DeleteMode.ToString();" to view the data in a text box, so it seems I might just be setting the selected item incorrectly?
The issue is that setting ComboBox.SelectedItem doesn't work unless the ComboBox contains the item you are setting it to. In your case your ComboBox is filled with three ComboBoxItem objects which have their Content property set to a string. So ComboBox.SelectedItem is a ComboBoxItem. You are trying to set the ComboBox.SelectedItem to a string, which will not equal any of the objects contained in the ComboBox. Therefore, nothing happens.
I would suggest setting up Binding for your ComboBox like here:
<ComboBox ItemsSource="{Binding DeleteModes}" SelectedItem="{Binding SelectedDeleteMode}" />
And then create a ViewModel to bind to. If you bind an Enum to a ComboBox it will display correctly so you won't need to call DeleteMode.ToString():
public class ViewModel : INotifyPropertyChanged
{
public ViewModel()
{
DeleteModes = new ObservableCollection<DeleteMode>
{ DeleteMode.HardDelete, DeleteMode.SoftDelete,
DeleteMode.MoveToDeletedItems };
}
public event PropertyChangedEventHandler PropertyChanged;
DeleteMode _selected_delete_mode;
public DeleteMode SelectedDeleteMode {
get { return _selected_delete_mode; }
set {
_selected_delete_mode = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("SelectedDeleteMode"));
}
}
ObservableCollection<DeleteMode> _delete_modes;
public ObservableCollection<DeleteMode> DeleteModes {
get { return _delete_modes; }
set {
_delete_modes = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("DeleteModes"));
}
}
public void update_mode(DeleteMode mode) => SelectedDeleteMode = mode;
}
I have a combobox binded to a table called Tenderness through MVVM. I'm using Entity Framework.It displays all the records properly, but I need to add another functionality to it. Suppose the user types in text which is not contained inside the combobox's Itemssource, I want to be able to add it directly to the table and then update the Itemssource as well. Now I have been able to do this without MVVM, I would want to know, how to achieve it using MVVM.
Just do what you did previously in the LostFocus event handler in the setter of a source property that you bind to the Text property of the ComboBox.
View Model:
public ObservableCollection<string> Items { get; } = new ObservableCollection<string>() { "a", "b", "c" };
private string _text;
public string Text
{
get { return _text; }
set
{
_text = value;
OnPropertyChanged(nameof(Text));
//add the missing value...
if (!Items.Contains(_text))
Items.Add(_text);
}
}
private string _selectedItem;
public string SelectedItem
{
get { return _selectedItem; }
set
{
_selectedItem = value;
OnPropertyChanged(nameof(SelectedItem));
}
}
View:
<ComboBox IsEditable="True" Text="{Binding Text, UpdateSourceTrigger=LostFocus}" ItemsSource="{Binding Items}"
SelectedItem="{Binding SelectedItem}" />
I have one ObservableCollection<M> fooBar {get;set;}. The class M.cs looks like this:
public class M{
private int _ID;
public int ID {
get {return this._ID;}
set {this._ID = value;}
}
private string _number;
public int Number {
get {return this._number;}
set {this._number = value;}
}
private string _power;
public int Power {
get {return this._power;}
set {this._power = value;}
}
/*
...
*/
}
Now I want to bind the names of these 3 propertys to a ComboBox. I don't want to do it like this:
<ComboBox>
<ComboBoxItem>ID</ComboBoxItem>
<ComboBoxItem>Number</ComboBoxItem>
<ComboBoxItem>Power</ComboBoxItem>
</ComboBox>
Is there a more comfortable way?
Based on the choose of the first ComboBox I want to fill the second ComboBox. As example I choose in the first ComboBox the property Numberthen the second ComboBox should look like this
<ComboBox
SelectedValue="{Binding ???}"
ItemsSource="{Binding fooBar}"
SelectedValuePath="Number"
DisplayMemberPath="Number"
/>
Maybe someone of you can help me, because I have no idea how to connect both comboboxes.
This is how I would do it:
Make a property on the view model which exposes the properties on the model (class M) which can be selected. This way you explicitly control which properties can be selected.
Make a property to hold the selected value of each combo box.
DisplayMemberPath/SelectedValuePath in ComboBox2 binds to the SelectedValue of ComboBox1.
ViewModel:
// ComboBox 1
public Dictionary<string, string> SelectableProperties = new Dictionary<string, string>()
{
{ nameof (M.ID), "ID" }
{ nameof (M.Number), "Nummer" }
{ nameof (M.Power), "Potenz" }
}
// Selection in combobox 1 (not strictly necessary as it can be handled in view, but you may need to know what SelectedValue represents)
private string _selectedValueMember = String.Empty;
public string SelectedValueMember
{
get { return _selectedValueMember; }
set { _selectedValueMember = value; }
}
// Selection in combobox 2 (object just in case there could be other values than int)
private object _selectedValue = null;
public object SelectedValue
{
get { return _selectedValue; }
set { _selectedValue = value; }
}
public ObservableCollection<M> FooBar{ get; set; }
View:
<ComboBox x:Name="ComboBox1"
Width="100"
Margin="5"
SelectedValuePath="Key"
DisplayMemberPath="Value"
SelectedValue="{Binding SelectedValueMember}"
ItemsSource="{Binding SelectableProperties}">
</ComboBox>
<ComboBox Width="100"
Margin="5"
DisplayMemberPath="{Binding ElementName=ComboBox1, Path=SelectedValue}"
SelectedValuePath="{Binding ElementName=ComboBox1, Path=SelectedValue}"
SelectedValue="{Binding SelectedValue}"
ItemsSource="{Binding FooBar}">
</ComboBox>
For the 1st ComboBox: Use Reflection to get the names of all the properties of class M and put those into the ComboBox.
For the 2nd ComboBox: When selection changes in the 1st one, you get the property name. Now set the SelectedValue binding to the property that was selected in the 1st ComboBox.
I have a view which contains a ListBox and a RichTextBox. My ListBox is bound to an ObservableCollection and works great:
<ListBox Name="checkListBox1" ItemsSource="{Binding ModelviewArticleObservableList}" SelectedItem="{Binding SelectedArticle, UpdateSourceTrigger=PropertyChanged}" DisplayMemberPath="ArticleHeader" />
I now want to bind my RichTextBox text to the SelectedItem of my ListBox, displaying a different column from the ObservableCollection (ArticleBody).
Here's my exposed string property in my ViewModel:
private string _SelectedArticle;
public string SelectedArticle
{
get { return _SelectedArticle; }
set
{
_SelectedArticle = value;
OnPropertyChanged("SelectedArticle");
}
}
& here's my current RichTextBox Xaml:
<xctk:RichTextBox Name="richTextBox1" Text="{Binding SelectedArticle, Mode=TwoWay}" />
Now, the selected item is fired on ListBox selection but my RichTextBox text is obviously displaying the class name rather than the ArticleBody text which I want.
How do I get my SelectedArticle string property to return the ArticleBody as opposed to the class name?
Since ModelviewArticleObservableList is ObservableCollection<viewArticle> change SelectedArticle to be of a viewArticle type (same as your collection item type)
private viewArticle _SelectedArticle;
public viewArticle SelectedArticle
{
get { return _SelectedArticle; }
set
{
_SelectedArticle = value;
OnPropertyChanged("SelectedArticle");
}
}
and then change RichTextBox binding to use SelectedArticle.ArticleBody path
<xctk:RichTextBox Name="richTextBox1" Text="{Binding SelectedArticle.ArticleBody, Mode=TwoWay}" />
I have a combo box that is bound to a list of model objects. I've bound the combo box SelectedItem to a property that is the model type. All of my data binding works beautifully after the window has been loaded. The SelectedItem is set properly and I'm able to save the object directly with the repository.
The problem is when the window first loads I initialize the SelectedItem property and my combobox displays nothing. Before I moved to binding to objects I was binding to a list of strings and that worked just fine on initialization. I know I'm missing something but I can't figure it out.
Thanks in advance for any guidance you can provide.
(One note about the layout of this page. The combo boxes are actually part of another ItemTemplate that is used in a ListView. The ListView is bound to an observable collection in the main MV. Each item of this observable collection is itself a ModelView. It is that second ModelView that has the SelectedItem property.)
Here is my Model:
public class DistributionListModel : Notifier, IComparable
{
private string m_code;
private string m_description;
public string Code
{
get { return m_code; }
set { m_code = value; OnPropertyChanged("Code"); }
}
public string Name
{
get { return m_description; }
set { m_description = value; OnPropertyChanged("Name"); }
}
#region IComparable Members
public int CompareTo(object obj)
{
DistributionListModel compareObj = obj as DistributionListModel;
if (compareObj == null)
return 1;
return Code.CompareTo(compareObj.Code);
}
#endregion
}
Here the pertinent code in my ModelView:
public MailRoutingConfigurationViewModel(int agencyID)
: base()
{
m_agencyID = agencyID;
m_agencyName = DataManager.QueryEngine.GetAgencyName(agencyID);
IntializeValuesFromConfiguration(DataManager.MailQueryEngine.GetMailRoutingConfiguration(agencyID));
// reset modified flag
m_modified = false;
}
private void IntializeValuesFromConfiguration(RecordCheckMailRoutingConfiguration configuration)
{
SelectedDistributionList = ConfigurationRepository.Instance.GetDistributionListByCode(configuration.DistributionCode);
}
public DistributionListModel SelectedDistributionList
{
get { return m_selectedDistributionList; }
set
{
m_selectedDistributionList = value;
m_modified = true;
OnPropertyChanged("SelectedDistributionList");
}
}
And finally the pertinent XAML:
<UserControl.Resources>
<DataTemplate x:Key="DistributionListTemplate">
<Label Content="{Binding Path=Name}" />
</DataTemplate>
</UserControl.Resources>
<ComboBox
ItemsSource="{Binding Source={StaticResource DistributionCodeViewSource}, Mode=OneWay}"
ItemTemplate="{StaticResource DistributionListTemplate}"
SelectedItem="{Binding Path=SelectedDistributionList, Mode=TwoWay}"
IsSynchronizedWithCurrentItem="False"
/>
#SRM, if I understand correctly your problem is binding your comboBox to a collection of objects rather than a collection of values types ( like string or int- although string is not value type).
I would suggest add a two more properties on your combobox
<ComboBox
ItemsSource="{Binding Source={StaticResource DistributionCodeViewSource},
Mode=OneWay}"
ItemTemplate="{StaticResource DistributionListTemplate}"
SelectedItem="{Binding Path=SelectedDistributionList, Mode=TwoWay}"
SelectedValuePath="Code"
SelectedValue="{Binding SelectedDistributionList.Code }"/>
I am assuming here that DistributionListModel objects are identified by their Code.
The two properties I added SelectedValuePath and SelectedValue help the combobox identify what properties to use to mark select the ComboBoxItem by the popup control inside the combobox.
SelectedValuePath is used by the ItemSource and SelectedValue by for the TextBox.
don't call your IntializeValuesFromConfiguration from the constructor, but after the load of the view.
A way to achieve that is to create a command in your viewmodel that run this method, and then call the command in the loaded event.
With MVVM light toolkit, you can use the EventToCommand behavior... don't know mvvm framework you are using but there would probably be something like this.