Why is that whenever I try to put SlectedIndex to 0, it always remains -1 ?
public partial class Window1 : Window
{
private ObservableCollection<string> _dropDownValues = new ObservableCollection<string>();
public ObservableCollection<string> DropDownValues
{
get { return _dropDownValues; }
set { _dropDownValues = value; }
}
private string _selectedValue;
public string SelectedValue
{
get { return _selectedValue; }
set { _selectedValue = value; }
}
public Window1()
{
InitializeComponent();
DataContext = this;
DropDownValues.Add("item1");
DropDownValues.Add("item2");
DropDownValues.Add("item3");
DropDownValues.Add("item4");
DropDownValues.Add("item5");
DropDownValues.Add("item6");
if (combotest.SelectedIndex == -1)
{
combotest.SelectedIndex = 0;
}
}
}
<StackPanel HorizontalAlignment="Left" Margin="10">
<ComboBox Name="combotest"
Margin="0 0 0 5"
ItemsSource="{Binding DropDownValues}"
SelectedValue="{Binding SelectedValue}"
Width="150"/>
</StackPanel>
Please correct me if I am wrong, but you havent set the SelectedValuePath in your XAML. Also once you set SelectedValuePath, you only need to set the default SelectedValue (same as the first item's value property from your items source) and there is no need for your SelectedIndex code.
Let me know if this helps.
Try this instead of setting the index.
string s = DropDownValues[0];
SelectedItem = s;
Related
I am binding a combobox with a varaible on my PLC so when i change the combobox the changed value transmitted to my PLC but when i change on my PLC the combobox wont change even if the field is changed
I put a brakepoint on the field(the one i bind to SelectedItem) to check if it changes and it did but didn't affect the combobox
Here is my ViewModel
List<string> _temperatureList = new List<string> { "80 °C", "100 °C", "120 °C" };
public List<string> TemperatureList
{
get { return _temperatureList; }
}
public string Temperature
{
get
{
return (TemperatureGS != 0) ? string.Format("{0} °C", TemperatureGS) : "80 °C";
}
set
{
TemperatureGS = Convert.ToSByte(value.Replace(" °C", ""));
OnPropertyChanged();
WriteTemperature(TemperatureGS);
}
}
private short _temperature ;
public short TemperatureGS
{
get { return _temperature; }
set { SetProperty(ref _temperature, value); }
}
public void OnNavigatedTo(NavigationContext navigationContext)
{
TemperatureGS = PLCread(0);
OnPropertyChanged(Temperature);
}
My Xaml code
<ComboBox SelectedItem="{Binding Temperature, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged }"
ItemsSource="{Binding TemperatureList }" />
I'm selecting an item from a combobox to filter a listview of items. The items contain values, and are displayed in a View depending on the filter selection.
<ComboBox Name="YearComboBox" ItemsSource="{x:Bind StudentEnrollment.Years, Mode=OneWay}" SelectedValue="{x:Bind StudentEnrollment.SelectedYear, Mode=TwoWay}”/>
<ListView ItemsSource="{x:Bind StudentEnrollment.FilteredStudentEnrollments, Mode=OneWay}" SelectedIndex="{x:Bind StudentEnrollment.SelectedIndex, Mode=TwoWay}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="viewModels:StudentViewModel" >
<StackPanel Orientation="Horizontal">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{x:Bind Score01, Mode=OneWay}"/>
</Grid>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
public class StudentEnrollmentViewModel : NotificationBase
{
StudentEnrollment StudentEnrollment;
public StudentEnrollmentViewModel()
{
}
private ObservableCollection<StudentEnrollmentViewModel> _StudentEnrollments;
public ObservableCollection<StudentEnrollmentViewModel> StudentEnrollments
{
get { return _StudentEnrollments; }
set
{
SetProperty(ref _StudentEnrollments, value);
}
}
private ObservableCollection<StudentEnrollmentViewModel> _FilteredStudentEnrollments;
public ObservableCollection<StudentEnrollmentViewModel> FilteredStudentEnrollments
{
get { return _FilteredStudentEnrollments; }
set
{
SetProperty(ref _FilteredStudentEnrollments, value);
}
}
private string _selectedYear;
public string SelectedYear
{
get
{
return _selectedYear;
}
set { SetProperty(ref _selectedYear, value);
{ RaisePropertyChanged(SelectedYear); }
RefreshFilteredStudentEnrollmentData(); }
}
private double _Score01;
public double Score01
{
get
{
_Score01 = FilteredStudentEnrollments.Where(y => y.Year == SelectedYear).Select(s => s.Score01).Sum();
return _Score01;
}
}
private void RefreshFilteredStudentEnrollmentData()
{
var se = from seobjs in StudentEnrollments
where seobjs.Year == SelectedYear
select seobjs;
if (FilteredStudentEnrollments.Count == se.Count()) || FilteredStudentEnrollments == null
return;
FilteredStudentEnrollments = new ObservableCollection<StudentEnrollmentViewModel>(se);
}
As expected I can sum the filtered values, and display the total in a TextBlock text property per listview column when the page loads.
<TextBlock Text="{x:Bind StudentEnrollment.Score01, Mode=OneWay}"/>
The issue's the Textblock UI does not update/display the changing property value in the viewmodel via a combobox selection. I sure I'm missing something, or have some logic backwards, hoping some fresh eyes can help.
I am not sure which class is which, because there seems to be some mix up between StudentEnrollmentViewModel and StudentViewModel, but I think I see the reason for the problem.
The Score01 property is a get-only property (actually you can get rid of the _Score01 field and just return the value). Its value is dependent on the FilteredStudentEnrollments and SelectedYear properties. But the UI does not know that so you have to notify it when these properties change that it should bind a new value of Score01 as well:
private ObservableCollection<StudentEnrollmentViewModel> _FilteredStudentEnrollments;
public ObservableCollection<StudentEnrollmentViewModel> FilteredStudentEnrollments
{
get { return _FilteredStudentEnrollments; }
set
{
SetProperty(ref _FilteredStudentEnrollments, value);
RaisePropertyChanged("Score01");
}
}
private string _selectedYear;
public string SelectedYear
{
get
{
return _selectedYear;
}
set
{
SetProperty(ref _selectedYear, value);
RaisePropertyChanged("Score01");
RefreshFilteredStudentEnrollmentData();
}
}
public double Score01
{
get
{
return FilteredStudentEnrollments.
Where(y => y.Year == SelectedYear).Select(s => s.Score01).Sum();
}
}
Notice I have changed the RaisePropertyChanged call to pass in "Score01", as the method expects the name of the property, whereas you were previously passing the value of the SelectedYear property, which meant the PropertyChanged event executed for something like 2018 instead of the property itself. Also note that SetProperty method internally calls RaisePropertyChanged for SelectedYear property as well.
So I have very simple combobox containing list of values. I am supposed to bind the selectedvalue to a viewmodel property and store it in DB. Below is my current approach:
SampleViewModel.cs
public class SampleViewModel: BindableBase
{
public SampleViewModel()
{
MyDetails = new ObservableCollection<DetailItems>(){
new DetailItems{Name="Detail1"},
new DetailItems{Name = "Detail2"},
new DetailItems{Name= "Detail3"},
new DetailItems{Name="Detail4"}
};
}
private ObservableCollection<DetailItems> _myDetails;
private string _myDetail;
public ObservableCollection<DetailItems> MyDetails { get { return _myDetails; } set { SetProperty(ref _myDetails, value); } }
public string MyDetail { get { return _myDetail; } set { SetProperty(ref _myDetail, value); } }
}
public class DetailItems: BindableBase
{
private string _name;
public string Name { get { return _name; } set { SetProperty(ref _name, value); } }
}
and my ComboBox in View is as follows
<ComboBox x:Name="cbDetails"
ItemsSource="{Binding MyDetails}"
DisplayMemberPath="Name"
SelectedValuePath="{Binding Path=Name}"
SelectedValue="{Binding MyDetail}"/>
But whenever I get data in backend, the string MyDetail will have an instance of DetailItems converted to string. Could anyone let me know how I can change this to bind appropriate value to MyDetail?
The reason is quite simple: SelectedValuePath expects path to the property of object, not binding (just like DisplayMemberPath does). So a fix would be:
<ComboBox x:Name="cbDetails"
ItemsSource="{Binding MyDetails}"
DisplayMemberPath="Name"
SelectedValuePath="Name"
SelectedValue="{Binding MyDetail}"/>
Obviously, SelectedValue always holds the currently selected item only. So you have to change the type from string to DetailItems as follow,
private DetailItems_myDetail;
public DetailItems MyDetail { get { return _myDetail; } set { SetProperty(ref _myDetail, value); } }
}
if you want the selected name call MyDetail.Name it will return your string
I have a Combobox with a concate string in displaymemberpath ('DescriptionComplete' in code-behind below), and that is what i get in the editable field BUT this is only the IdEchantillon that i want into the editable field...
How must i do please ?
XAML:
<ComboBox x:Name="cbEchantillon" SelectedValue="{Binding CurrentEchantillon.IdEchantillon}" ItemsSource="{Binding OcEchantillon}" DisplayMemberPath="DescriptionComplete" SelectedValuePath="IdEchantillon" SelectedItem="{Binding CurrentEchantillon}" Text="{Binding IdEchantillon}" IsEditable="True" Width="355" FontSize="14" FontFamily="Courier New" SelectionChanged="cbEchantillon_SelectionChanged"></ComboBox>
Code behind:
public class Echantillon : ViewModelBase
{
private string _IdEchantillon;
private string _Description;
private DateTime _dateechan;
private string _descriptionComplete;
}
public string IdEchantillon
{
get { return _IdEchantillon; }
set { _IdEchantillon = value; RaisePropertyChanged("IdEchantillon"); }
}
public string Description
{
get { return _Description; }
set { _Description = value; RaisePropertyChanged("Description"); }
}
public DateTime Dateechan
{
get { return _dateechan; }
set { _dateechan = value; RaisePropertyChanged("Dateechan"); }
}
public string DescriptionComplete
{
get { return string.Format("{0} {1} {2}", IdEchantillon.PadRight(20), Dateechan.ToShortDateString(), Description); }
set { _descriptionComplete = value; }
}
}
At first, please, cleanup your ComboBox property bindings. You should not create binding for SelectedValue, because you already have binding for SelectedItem property. The SelectedValue is determined by extracting the value by SelectedValuePath from the SelectedItem.
In case of binding to ViewModel, you should not also bind Text property. Use ItemsSource as you do, and set DisplayMemberPath property to what you want to show as the text representation of the every item in the bound collection.
Tried all the solutions for similar issues around here, still no go. I have a ComboBox that should work for selection of existing items and/or for adding new ones. Only the selected item part works. Category is just an object with a Name and Id.
Thanks in advance!
XAML
<ComboBox Name="CbCategory" ItemsSource="{Binding Categories}"
SelectedItem="{Binding SelectedCategory.Name, UpdateSourceTrigger=PropertyChanged}"
Text="{Binding NewCategory.Name}" DisplayMemberPath="Name"
IsEditable="True"/>
Code behind
private Category _selectedCategory;
public Category SelectedCategory
{
get { return _selectedCategory; }
set
{
if (Equals(_selectedCategory, value)) return;
_selectedCategory = value;
SendPropertyChanged("SelectedCategory");
}
}
private Category _newCategory;
public Category NewCategory
{
get { return _newCategory; }
set
{
if (Equals(_newCategory, value)) return;
_newCategory = value;
SendPropertyChanged("NewCategory");
}
}
Your Text Binding doesn't work because you're binding against a null Category property. Instantiate it instead.
public Category NewCategory
{
get { return _newCategory ?? (_newCategory = new Category()); }
set
{
if (Equals(_newCategory, value)) return;
_newCategory = value;
SendPropertyChanged("NewCategory");
}
}
Edit: Elaborating as per your comment:
Your ComboBox.Text binding is set to "{Binding NewCategory.Name}", so no matter what the value of SelectedCategory is, the Text property will always reflect the name of the NewCategory.
When NewCategory is null, the Text property has nothing to bind to, and therefore the 2-way binding cannot be executed (that is, the value of the Text property cannot be passed back to NewCategory.Name, because that will cause an NullReferenceException (because the NewCategory is null).
This does not affect the case of the SelectedItem, because that's binding directly to the SelectedCategory property, and not a sub-property of that.
Create new varible to keep text of combobox. If the selectedItem having null value get the text of combobox as new Item,
Code :
<ComboBox Name="CbCategory" ItemsSource="{Binding Categories}"
SelectedItem="{Binding SelectedCategory.Name, UpdateSourceTrigger=PropertyChanged}"
Text="{Binding Name}" DisplayMemberPath="Name"
IsEditable="True"/>
private String _name;
public Category Name
{
get { return _name; }
set
{
_name = value
SendPropertyChanged("Name");
}
}
public ICommand ItemChange
{
get
{
`return new RelayCommand(() =>`{
try{string item = this.SelectedCategory.Code;}
catch(Exception ex){string item = this.Name;}
}, () => { return true; });
}
}