Reputation: 2103
I'm using a ComboBox to display a list of ZoomLevels (e.g. normal, large, xxl), the selected ZoomLevel is bound to the variable "ZoomLevel" in my MainViewModel.
<ComboBox ItemsSource="{Binding ZoomLevels}"
SelectedItem="{Binding ZoomLevel}"
IsSynchronizedWithCurrentItem="True"
DisplayMemberPath="Name"
SelectedValuePath="Name"/>
On application start, the initial ZoomLevel is loaded from the settings and might be set to "xxl", e.g.
My problem is that during initialization of the ComboBox, the setter of "ZoomLevel" is called with the first ZoomLevel in the bound collection "ZoomLevels".
This overwrites the value for "ZoomLevel" loaded from the settings and it's always the first ZoomLevel that is selected in the combobox.
What is the problem here? If I remove IsSynchronizedWithCurrentItem
, then the ZoomLevel is initialized correctly. However, the Combobox is then not in sync with the currently selected ZoomLevel, which it should be.
EDIT: relevant code from my MainViewModel:
public class ZoomLevel
{
public string Name { get; set; }
public double ZoomLevelValue { get; set; }
}
public MainViewModel()
{
...
// Load zoom level
var userDefinedZoom = ZoomLevels.FirstOrDefault(x => x.ZoomLevelValue == Settings.Default.ZoomLevelValue);
ZoomLevel = userDefinedZoom ?? ZoomLevels[0];
}
/// <summary>
/// Zoom level of application, initialized in the constructor
/// </summary>
private ZoomLevel _zoomLevel;
public ZoomLevel ZoomLevel
{
get { return _zoomLevel; }
set
{
_zoomLevel = value;
Settings.Default.ZoomLevelValue = value.ZoomLevelValue;
Settings.Default.Save();
RaisePropertyChanged("ZoomLevel");
}
/// <summary>
/// all available zoom levels
/// </summary>
public ObservableCollection<ZoomLevel> ZoomLevels
{
get
{
return new ObservableCollection<ZoomLevel>()
{
new ZoomLevel() { Name="normal", ZoomLevelValue = 1 },
new ZoomLevel() { Name="large", ZoomLevelValue = 1.2 },
new ZoomLevel() { Name="xxl", ZoomLevelValue = 1.4 },
};
}
}
Upvotes: 0
Views: 146
Reputation: 128042
The SelectedItem
must be a member of the ItemsSource
collection.
You should therefore initialize the ZoomLevel
property with that instance of the ZoomLevels
that corresponds to the current default value:
public MainViewModel()
{
ZoomLevels = new List<ZoomLevel>()
{
new ZoomLevel { Name = "normal", ZoomLevelValue = 1 },
new ZoomLevel { Name = "large", ZoomLevelValue = 1.2 },
new ZoomLevel { Name = "xxl", ZoomLevelValue = 1.4 },
};
// here
ZoomLevel = ZoomLevels.FirstOrDefault(
z => z.ZoomLevelValue == Settings.Default.ZoomLevelValue);
}
public List<ZoomLevel> ZoomLevels { get; private set; }
Note also that if the ZoomLevels
collection never changes, it is not necessary that it is an ObservableCollection.
Besides that, setting the SelectedValuePath
of the ComboBox only makes sense in conjunction with SelectedValue
. As you are using SelectedItem
, it is redundant.
Upvotes: 1