Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
146 views
in Technique[技术] by (71.8m points)

WPF MVVM Combobox SelectedItem not working properly

I've already searched and read from several posts but I couldn't find what I am doing wrong.

I have a ComboBox with an ObservableCollection<string> Available_COMPorts as ItemsSource. On SelectedValue I binded a string named SelectedCOMPort with Mode = TwoWay.

<Label Content="Porta COM: "></Label>
<ComboBox ItemsSource="{Binding Available_COMPorts}"
          SelectedValue="{Binding SelectedCOMPort, Mode=TwoWay}" />

After bofere the combobox, I have a Label displaying the SelectedCOMPort

<Label Content="Status: " />
<Label Content="{Binding SelectedCOMPort}" Foreground="Red" />

I have made both Available_COMPorts and SelectedCOMPort with INotifyPropertyChanged. On my ViewModel Initialization, I filled the Available_COMPorts with the three SerialPort strings available ("COM6", "COM5", "COM4") and set SelectedCOMPort = "Available_COMPorts[0]" ("COM6").

When I Run the code, ComboBox has the three itens, the selected item is "COM6" and the label shows "COM6" (everything is fine). Then I select "COM5" and the label updates it's value to "COM5". This is presented on the following pictures.

Image with SelectedCOMPort = "COM6", by default on ViewModel initialization

Image with SelectedCOMPort = "COM5", after selecting directly on the ComboBox

The problem is when I try to access SelectedCOMPort on the ViewModel, as I need the selected item to connect on my SerialPort. The SelectedCOMPort is always as the default value "COM6". I try to access the SelectedCOMPorton the connect click command.

Debbuging, using Breakpoints on INotifyProperty functions I realized that the binding property seems to be working fine, but when it leaves INotifyProperty the value goes back to default.

Why is that happening? I've tryed several approachs and none worked for me.

Following is my ViewModel and BaseViewModel with INotifyProperty:

BaseViewModel : INotifyPropertyChanged

public class BaseViewModel : INotifyPropertyChanged
{
    #region PropertyChange
    public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged([CallerMemberName] string propertyName = "")
    {
        if (PropertyChanged != null)
        {
            PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    protected void SetProperty<T>(ref T backingField, T value, [CallerMemberName] string propertyName = null)
    {
        if (EqualityComparer<T>.Default.Equals(backingField, value)) return;
        backingField = value;
        OnPropertyChanged(propertyName);
    }
    #endregion
}

ViewModel

public class LiveGraphViewModel : BaseViewModel
{
    public ConnectButtonCommand ConnectButtonCommand { get; set; }
    private ObservableCollection<string> _availableCOMPorts;
    private string _selectedCOMPort;

    public ObservableCollection<string> Available_COMPorts
    {
        get { return _availableCOMPorts; }
        set { SetProperty(ref _availableCOMPorts, value); }
    }
    public string SelectedCOMPort
    {
        get {  return _selectedCOMPort; }
        set { SetProperty(ref _selectedCOMPort, value); }
    }
    public LiveGraphViewModel()
    {
        this.ConnectButtonCommand = new ConnectButtonCommand(this);
        ObservableCollection<string> TempCOM = new ObservableCollection<string>();
        foreach (string comport in SerialPort.GetPortNames())
            TempCOM.Add(comport);
        Available_COMPorts = TempCOM;
        if(Available_COMPorts.Count > 0)
            SelectedCOMPort = Available_COMPorts[0];
    }

    public void ConnectButton()
    {
        if (SelectedCOMPort == "COM5")
            Connect(SelectedCOMPort);
    }

}

LiveGraphView XAML

<UserControl x:Class="SmartAthleticsWPF.Views.LiveGraphView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:SmartAthleticsWPF.Views" 
             xmlns:viewmodels="clr-namespace:SmartAthleticsWPF.ViewModels"
             xmlns:commands="clr-namespace:SmartAthleticsWPF.Commands"
             xmlns:syncfusion="clr-namespace:Syncfusion.UI.Xaml.Charts;assembly=Syncfusion.SfChart.WPF"
             xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">

    <UserControl.Resources>
        <viewmodels:LiveGraphViewModel x:Key="LIVviewModel"/>
    </UserControl.Resources>

    <Grid Background="#EDEDED">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="0.01*"/>
            <ColumnDefinition Width="1*"/>
            <ColumnDefinition Width="1*"/>
            <ColumnDefinition Width="0.5*"/>
            <ColumnDefinition Width="0.01*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="0.1*"/>
            <RowDefinition Height="1.2*"/>
            <RowDefinition Height="2*"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="0.1*"/>
        </Grid.RowDefinitions>
        
        <!--LIVE GRAPH BORDER-->
        <Border Grid.Row="1" Grid.RowSpan="2" 
                Grid.Column="1" Grid.ColumnSpan="2"
                Margin="5" 
                BorderBrush="Black" 
                BorderThickness="2" 
                CornerRadius="5"
                Padding="10,10,30,10"
                HorizontalAlignment="Stretch" VerticalAlignment="Stretch">

            <DockPanel>
                <Label Content="Live Graph" 
                       DockPanel.Dock="Top"
                       HorizontalAlignment="Center" 
                       Padding="0,5,0,10" FontSize="22"/>

                <syncfusion:SfChart x:Name="LiveGraphChart" >
                    <syncfusion:SfChart.PrimaryAxis>
                        <syncfusion:NumericalAxis Header="Seconds" 
                                          Maximum="{Binding MaxXAxis}"
                                          Minimum="{Binding MinXAxis}"/>
                    </syncfusion:SfChart.PrimaryAxis>
                    <syncfusion:SfChart.SecondaryAxis>
                        <syncfusion:NumericalAxis Header="Kgf"/>
                    </syncfusion:SfChart.SecondaryAxis>

                    <syncfusion:SfChart.Series>
                        <syncfusion:FastLineBitmapSeries ItemsSource="{Binding FyCircularBuffer}" 
                                                         XBindingPath="XData" YBindingPath="YData" 
                                                         StrokeThickness="1" Interior="DarkGreen" 
                                                         ShowTooltip="False" ShowTrackballInfo="False" 
                                                         IsSeriesVisible="{Binding FyChecked}"/>
                        <syncfusion:FastLineBitmapSeries ItemsSource="{Binding MyCircularBuffer}" 
                                                         XBindingPath="XData" YBindingPath="YData" 
                                                         StrokeThickness="1" Interior="LimeGreen" 
                                                         ShowTooltip="False" ShowTrackballInfo="False" 
                                                         IsSeriesVisible="{Binding MyChecked}"/>
                        <syncfusion:FastLineBitmapSeries ItemsSource="{Binding FxCircularBuffer}" 
                                                         XBindingPath="XData" YBindingPath="YData" 
                                                         StrokeThickness="1" Interior="IndianRed" 
                                                         ShowTooltip="False" ShowTrackballInfo="False"
                                                         IsSeriesVisible="{Binding FxChecked}"/>
                        <syncfusion:FastLineBitmapSeries ItemsSource="{Binding MxCircularBuffer}" 
                                                         XBindingPath="XData" YBindingPath="YData" 
                                                         StrokeThickness="1" Interior="Red" 
                                                         ShowTooltip="False" ShowTrackballInfo="False"
                                                         IsSeriesVisible="{Binding MxChecked}"/>
                        <syncfusion:FastLineBitmapSeries ItemsSource="{Binding FzCircularBuffer}" 
                                                         XBindingPath="XData" YBindingPath="YData" 
                                                         StrokeThickness="1" Interior="BlueViolet" 
                                                         ShowTooltip="False" ShowTrackballInfo="False"
                                                         IsSeriesVisible="{Binding FzChecked}"/>
                        <syncfusion:FastLineBitmapSeries ItemsSource="{Binding MzCircularBuffer}" 
                                                         XBindingPath="XData" YBindingPath="YData" 
                                                         StrokeThickness="1" Interior="Blue" 
                                                         ShowTooltip="False" ShowTrackballInfo="False"
                                                         IsSeriesVisible="{Binding MzChecked}"/>
                    </syncfusion:SfChart.Series>

                </syncfusion:SfChart>
            </DockPanel>
        </Border>

        <!--COP BORDER-->
        <Border G

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

As mentioned by @Clemens I had two view model instances at the same time. One created in the UserControl's constructor (code behind) and other on the XAML Resources.

So, I removed the last one and everything works fine.

<!--
<UserControl.Resources>
    <viewmodels:LiveGraphViewModel x:Key="LIVviewModel"/>
</UserControl.Resources>
-->

<Label Content="Porta COM: "></Label>
<ComboBox ItemsSource="{Binding Available_COMPorts}"
          SelectedValue="{Binding SelectedCOMPort, Mode=TwoWay}" />
<Button Content="Connect/Disconnect" 
        Command="{Binding Path=ConnectButtonCommand}" />


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...