Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement toolbars when using the MVVM pattern?

I´m creating a project using a serial port. I'm practicing using MVVM model. I need to setup the serial port, so I'm using a toolbar.

This is my model:

public class Port : INotifyPropertyChanged, IDataErrorInfo
{
    private SerialPort _serialPort;

    public Port()
    {
        _serialPort = new SerialPort();
    }

    public string PortName
    {
        get { return _serialPort.PortName; }
        set
        {
            _serialPort.PortName = value;
            OnPropertyChanged("PortName");
        }
    }

    public int BaudRate
    {
        get { return _serialPort.BaudRate; }
        set
        {
            _serialPort.BaudRate = value;
            OnPropertyChanged("BaudRate");
        }
    }

    public Parity Parity
    {
        get { return _serialPort.Parity; }
        set
        {
            _serialPort.Parity = value;
            OnPropertyChanged("Parity");
        }
    }

    public int DataBits
    {
        get { return _serialPort.DataBits; }
        set
        {
            _serialPort.DataBits = value;
            OnPropertyChanged("PortDataBits");
        }
    }

    public StopBits StopBits
    {
        get { return _serialPort.StopBits; }
        set
        {
            _serialPort.StopBits = value;
            OnPropertyChanged("PortStopBits");
        }
    }

    public Handshake Handshake
    {
        get { return _serialPort.Handshake; }
        set
        {
            _serialPort.Handshake = value;
            OnPropertyChanged("PortHandshake");
        }
    }

    public string[] AvailablePortNames
    {
        get { return SerialPort.GetPortNames(); }
    }

    #region IDataErrorInfo Members

    string IDataErrorInfo.Error { get { return null; } }

    string IDataErrorInfo.this[string propertyName]
    {
        get { return this.GetValidationError(propertyName); }
    }

    #endregion // IDataErrorInfo Members

    #region Validation

    /// <summary>
    /// Returns true if this object has no validation errors.
    /// </summary>
    public bool IsValid
    {
        get
        {
            foreach (string property in ValidatedProperties)
                if (GetValidationError(property) != null)
                    return false;

            return true;
        }
    }

    static readonly string[] ValidatedProperties = 
    { 
        "PortName",
    };

    string GetValidationError(string propertyName)
    {
        if (Array.IndexOf(ValidatedProperties, propertyName) < 0)
            return null;

        string error = null;

        switch (propertyName)
        {
            case "PortName":
                ValidatePortName();
                break;

            default:
                Debug.Fail("Unexpected property being validated on Port: " + propertyName);
                break;
        }

        return error;
    }

    string ValidatePortName()
    {
        if (IsStringMissing(this.PortName))
        {
            return Strings.Port_Error_MissingName;
        }
        return null;
    }

    #endregion // Validation

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
        this.VerifyPropertyName(propertyName);

        PropertyChangedEventHandler handler = this.PropertyChanged;
        if (handler != null)
        {
            var e = new PropertyChangedEventArgs(propertyName);
            handler(this, e);
        }
    }

    #endregion // INotifyPropertyChanged Members
}

Then, I've got a SetupPortView:

<UserControl 
    x:Class="PortChat.View.SetupPortView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:vw="clr-namespace:PortChat.View"
>
<ToolBar>
    <Label Content="COM Port:"
      Target="{Binding ElementName=AvailablePortsComboBox}" 
    />
    <ComboBox 
      x:Name="AvailablePortsComboBox"
      Width="80"
      ItemsSource="{Binding Path=AvailablePortNames, Mode=OneTime}"
      SelectedItem="{Binding Path=PortName, ValidatesOnDataErrors=True}"
      Validation.ErrorTemplate="{x:Null}"
      />
      ...

My question is, when the user press CONNECT button, create the port with that setup. I'm not sure if I'm creating the right model. In my class MainWindowViewModel, I created a Port variable, but I guess this is not correct.

How can I improve this code and create the Port object using MVVM (I have no idea using MVVM in toolbar using textBoxes)?

like image 321
oscar.fimbres Avatar asked Oct 09 '11 06:10

oscar.fimbres


1 Answers

I would change the bindings of the ComboBox. I'd bind the ComboBox to a collection of Ports (not names) and also bind the SelectedItem of the ComboBox to a SelectedPort property on the ViewModel.

That way you know what port has been selected by the user and there is no need to query the collection for the correct port.

When you want to allow the user to create/configure a new port just add an empty/new Port object to the collection and set the SelectedPort to this newly added item.

like image 120
Emond Avatar answered Nov 14 '22 22:11

Emond