I want to achieve the following: I want to have a ComboBox which displays the available COM ports. On Startup (and clicking a "refresh" button) I want to get the available COM ports and set the selection to the last selected value (from the application settings).
If the value from the settings (last com port) is not in the list of values (available COM ports) following happens:
Although the ComboBox doesn't display anything (it's "clever enough" to know that the new SelectedItem is not in ItemsSource), the ViewModel is updated with the "invalid value". I actually expected that the Binding has the same value which the ComboBox displays.
Code for demonstration purposes:
MainWindow.xaml:
<Window x:Class="DemoComboBinding.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
xmlns:local="clr-namespace:DemoComboBinding">
<Window.Resources>
<local:DemoViewModel x:Key="vm" />
</Window.Resources>
<StackPanel Orientation="Vertical">
<ComboBox SelectedItem="{Binding Source={StaticResource vm}, Path=Selected}" x:Name="combo"
ItemsSource="{Binding Source={StaticResource vm}, Path=Source}"/>
<Button Click="Button_Click">Set different</Button> <!-- would be refresh button -->
<Label Content="{Binding Source={StaticResource vm}, Path=Selected}"/> <!-- shows the value from the view model -->
</StackPanel>
</Window>
MainWindow.xaml.cs:
// usings removed
namespace DemoComboBinding
{
public partial class MainWindow : Window
{
//...
private void Button_Click(object sender, RoutedEventArgs e)
{
combo.SelectedItem = "COM4"; // would be setting from Properties
}
}
}
ViewModel:
namespace DemoComboBinding
{
class DemoViewModel : INotifyPropertyChanged
{
string selected;
string[] source = { "COM1", "COM2", "COM3" };
public string[] Source
{
get { return source; }
set { source = value; }
}
public string Selected
{
get { return selected; }
set {
if(selected != value)
{
selected = value;
OnpropertyChanged("Selected");
}
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
void OnpropertyChanged(string propertyname)
{
var handler = PropertyChanged;
if(handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyname));
}
}
#endregion
}
}
A solution I initially came up with would be to check inside the Selected setter if the value to set is inside the list of available COM ports (if not, set to empty string and send OPC).
What I wonder: Why does that happen? Is there another solution I didn't see?