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}" />
Related
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");
}
}
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 a small problem with Combobox bindings in Windows Store app. It has to be bound to localized enumeration values (enumeration name is BackgroundTrack). I have 2 properties in view model - items list and selected item. I use Tuple<,> to hold enumeration value and its localized string representation.
Property for selected item in vm:
public Tuple<BackgroundTrack, String> SelectedBackgroundTrack
{
get
{
return _selectedBackgroundTrack;
}
set
{
if (_selectedBackgroundTrack == null ||
_selectedBackgroundTrack.Equals(value))
{
_selectedBackgroundTrack = value;
_settingsService.BackgroundTrack = value.Item1;
RaisePropertyChanged("SelectedBackgroundTrack");
}
}
}
Property for items list in vm:
public IEnumerable<Tuple<BackgroundTrack, String>> BackgroundTrackList { get; set; }
Combobox bindings:
<ComboBox
ItemsSource="{Binding Path=BackgroundTrackList}"
SelectedItem="{Binding Path=SelectedBackgroundTrack, Mode=TwoWay}"
Grid.Row="10" ItemTemplate="{StaticResource DataTemplate1}"
/>
<DataTemplate x:Key="DataTemplate1">
<Grid>
<TextBlock Text="{Binding Item2}"/>
</Grid>
</DataTemplate>
ViewModel constructor:
BackgroundTrackList = EnumUtils.GetLiterals<BackgroundTrack>();
SelectedBackgroundTrack = BackgroundTrackList.First(t => t.Item1.Equals(_settingsService.BackgroundTrack));
Problem: I'm setting selected item (from app settings) in ViewModel constructor, but this value does not show in combobox - it has nothing selected. If I select something in combobbox, the binding works correctly and sets the underlying ViewModel property. How do I correct this issue? Do I need to implement INotifyPropertyChanged or defer setting of selected item property programatically?
You need to implement IEquatable<T> on the type that is used for the item. Tuple does not.
You can't set both SelectedItem and SelectedValuePath at same time.
If you are using SelectedItem, remove SelectedValuePath and it will work as expected.
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.