0

Below are my files. While I run the command because of ComboBox, it is throwing some weird runtime exception as below.

enter image description here

Without ComboBox it runs well.

How can I improve my code such that it starts working with ComboBox?

VehicalForm.xaml

        <Window x:Class="Seris.VehicalForm"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="500" Width="600">
<Control>
    <Control.Template>
        <ControlTemplate>
            <WrapPanel Orientation="Vertical" Margin="10 " >
                <Label Content="Vehical No" HorizontalAlignment="Left"/>
                <TextBox Name="VehicalNo_Text" Height="23" Width="80" TextWrapping="Wrap" Text="{Binding VehicalNo}"  HorizontalAlignment="Left" />
                <Label Content="Model" HorizontalAlignment="Left"/>
                <TextBox Name="Model_Text" Height="23" Width="80" TextWrapping="Wrap" Text="{Binding Model}" HorizontalAlignment="Left" />
                <Label Content="Manufacturing Date" HorizontalAlignment="Left"/>
                <DatePicker Name="ManufacturingDate_DateTime" SelectedDate="{Binding ManufacturingDate, Mode=TwoWay}"/>
                <Label Content="IU No" HorizontalAlignment="Left"/>
                <TextBox Height="23" Width="80" Name="IUNO_Text" TextWrapping="Wrap" Text="{Binding IUNo}" HorizontalAlignment="Left"/>
                <Label Content="Personnel" HorizontalAlignment="Left"/>
                <ComboBox Name="Personnel_Combo" Loaded="{Binding Personnel_Combo_Loaded}" HorizontalAlignment="Left" Width="116"/>
                <Separator Height="20" RenderTransformOrigin="0.5,0.5" Width="16"/>
                <Button Name="Save_Button" Command="{Binding SaveButton_Command}" Content="Save" Width="66"/>
                <Label x:Name="Error_Label" Content="{Binding ErrorMessage, UpdateSourceTrigger=PropertyChanged}" Foreground="Red" HorizontalAlignment="Left" Height="41" Width="137"/>
                <ListView Name ="Grid" Height="294" Width="371" >
                    <DataGrid Name="DG" ItemsSource="{Binding ListItems, UpdateSourceTrigger=PropertyChanged}" SelectionUnit="Cell" GridLinesVisibility="None" IsReadOnly="True" AutoGenerateColumns="False" BorderThickness="0">
                        <DataGrid.Columns>
                            <DataGridTextColumn Header="Vehical No" Binding="{Binding VehicalNo}" />
                            <DataGridTextColumn Header="Model" Binding="{Binding Model}" />
                            <DataGridTextColumn Header="ManufacturingDate" Binding="{Binding ManufacturingDate}" />
                            <DataGridTextColumn Header="IUNo" Binding="{Binding IUNo}" />
                            <DataGridTextColumn Header="Personnel" Binding="{Binding Personnel}" />

                        </DataGrid.Columns>

                    </DataGrid>
                </ListView>
                <Label Name="Notification" Content="hjgj"/>

            </WrapPanel>
            <ControlTemplate.Triggers>
                <DataTrigger Binding="{Binding IsMouseOver, ElementName=Grid}" Value="true">
                    <Setter Property="Content" TargetName="Notification" Value="abc"/>


                </DataTrigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>
    </Control.Template>
</Control>
</Window>

VehicalMainViewModel.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Seris.Models;
using System.Collections.ObjectModel;
using System.Windows.Input;
using Seris.Commands;
using Seris.ViewModels;
using System.Windows;
using System.Windows.Controls;

namespace Seris.ViewModels
{
public class VehicalMainViewModel : ObservableObject
{
public ObservableCollection<VehicalModel> _listItems ;

private string _erroMesage;

public string ErrorMessage
{
    get { return _erroMesage; }
    set { _erroMesage = value; OnPropertyChanged("ErrorMessage"); }
}

public ObservableCollection<VehicalModel> ListItems
{
    get { return _listItems; }
    set
    {
        if (!value.Equals( _listItems))
        {
            _listItems = value;
        }
    }
}
    #region Getter-Setter
    private string _VehicalNo;

    public string VehicalNo 
    {
        get { return _VehicalNo; }
        set
        {
            if (value != _VehicalNo)
            {
                _VehicalNo = value.Trim();
                OnPropertyChanged("VehicalNo");

            }
        }
    }
    private string _Model;

    public string Model
    {
        get { return _Model; }
        set
        {
            if (value != _Model)
            {
                _Model = value.Trim();
                OnPropertyChanged("Model");
            }
        }
    }
    private DateTime? _ManufacturingDate;

    public DateTime? ManufacturingDate
    {
        get { return _ManufacturingDate; }
        set
        {
            if (value != _ManufacturingDate)
            {
                _ManufacturingDate = value;
                OnPropertyChanged("ManufacturingDate");
            }
        }
    }
    private string _IUNo;

    public string IUNo
    {
        get { return _IUNo; }
        set
        {
            if (value != _IUNo)
            {
                _IUNo = value.Trim();
                OnPropertyChanged("IUNo");
            }
        }
    }
    private ObservableCollection<string> _PersonnelName;

    public ObservableCollection<string> PersonnelName
    {
        get { return _PersonnelName; }
        set
        {
            if (value != _PersonnelName)
            {
                _PersonnelName = value;
                OnPropertyChanged("PersonnelName");
            }
        }
    } 
    #endregion

    private ICommand _saveButton_Command;

    public ICommand SaveButton_Command
    {
        get { return _saveButton_Command; }
        set { _saveButton_Command = value; }
    }



    public void Personnel_Combo_Loaded(object sender, RoutedEventArgs e)
    {
        var Personnel_ComboBox = sender as ComboBox;
        Personnel_ComboBox.ItemsSource = PersonnelName;
    }
    public void SaveToList(object o1)
    {
        ErrorMessage="";
        try
        {
            _listItems.Add(new VehicalModel(VehicalNo, Model, ManufacturingDate, IUNo, PersonnelName));
        }
        catch(Exception ex)
        {
            ErrorMessage = ex.Message;
        }
    }
    public void RemoveFromList()
    {

    }
    public VehicalMainViewModel()
    {
        ListItems = new ObservableCollection<VehicalModel>();
        PersonnelName = new ObservableCollection<string>() { "sd", "ad", "ad" };
        ErrorMessage = "";
        VehicalModel vm=new VehicalModel();
        SaveButton_Command = new RelayCommand(new Action<object>(SaveToList));

    }
}
}

VehicalModel.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using System.Text.RegularExpressions;

namespace Seris.Models
{
public class VehicalModel : ObservableObject
{
    #region Getter-Setter
    private string _VehicalNo;

    public string VehicalNo 
    {
        get { return _VehicalNo; }
        set
        {
            if (value != _VehicalNo)
            {
                _VehicalNo = value.Trim();
                OnPropertyChanged("VehicalNo");
            }
        }
    }
    private string _Model;

    public string Model
    {
        get { return _Model; }
        set
        {
            if (value != _Model)
            {
                _Model = value.Trim();
                OnPropertyChanged("Model");
            }
        }
    }
    private DateTime? _ManufacturingDate;

    public DateTime? ManufacturingDate
    {
        get { return _ManufacturingDate; }
        set
        {
            if (value != _ManufacturingDate)
            {
                _ManufacturingDate = value;
                OnPropertyChanged("ManufacturingDate");
            }
        }
    }
    private string _IUNo;

    public string IUNo
    {
        get { return _IUNo; }
        set
        {
            if (value != _IUNo)
            {
                _IUNo = value.Trim();
                OnPropertyChanged("IUNo");
            }
        }
    }
    private ObservableCollection<string> _PersonnelName;

    public ObservableCollection<string> PersonnelName
    {
        get { return _PersonnelName; }
        set
        {
            if (value != _PersonnelName)
            {
                _PersonnelName = value;
                OnPropertyChanged("PersonnelName");
            }
        }
    } 
    #endregion

    #region Constructor
    public VehicalModel(string VehicalNo, string Model, DateTime? ManufacturingDate, string IUNo, ObservableCollection<string> PersonnelName)
    {
        this.VehicalNo = VehicalNo;
        this.Model = Model;
        this.ManufacturingDate = ManufacturingDate;
        this.IUNo = IUNo;
        this.PersonnelName = PersonnelName;
        if(!(Validate_VehicalNo() && Validate_Model() && Validate_ManufacturingDate() && Validate_IUNo()))
            throw(new Exception("Invalid Data"));
    }
    public VehicalModel()
    {
        VehicalNo = null;
        Model = null;
        ManufacturingDate = null;
        IUNo = null;
        PersonnelName = new ObservableCollection<string>();

    } 
    #endregion

    #region Methods

    #region Validate Methods

    public bool Validate_VehicalNo()
    {
        if (VehicalNo == null)
            return false;
        if (matchRE(VehicalNo,"[A-Zz-z][A-Zz-z0-9]{6}"))
            return true;
        else
            return false;
    }
    public bool Validate_Model()
    {
        if (Model == null)
            return false;
        if(Model!=null || Model.Length==0)
            return true;
        else
            return false;
    }
    public bool Validate_ManufacturingDate()
    {
        if (ManufacturingDate == null)
            return false;
        return true;
    }
    public bool Validate_IUNo()
    {
        if (IUNo == null || Model.Length==0)
            return false;
        if(matchRE(IUNo,"[0-9]{10}"))
            return true;
        else
            return false;
    }
    public bool Validate_PersonnelName()
    {
        if (PersonnelName == null)
            return false;
        //if(matchRE(PersonnelName,"[A-Za-z]+"))
        //    return true;
        else
            return false;

    }  

    public bool matchRE(string stringToMatch, string regularExpression)
    {
        Regex regex = new Regex(@regularExpression);
        Match match = regex.Match(stringToMatch);

        if(match.Success)
            return(true);
        else
            return(false);
    }
    #endregion

    #endregion
}
}
Pratik
  • 161
  • 4
  • 13

2 Answers2

0

You cannot bind to an event, and FrameworkElement.Loaded is an event.

What you can do is create an ICommand (instead of an event handler) and look at some sort of Event To Command solution.


After reading what the event you are attempting to do is actually doing, I would actually recommend that you instead bind your collection to the ItemsSource property instead of trying to set the items source after the control is loaded. If you only want to bind it one time, you can always use the BindingMode.OneTime setting.

<ComboBox ItemsSource="{Binding Path=PersonnelName}" />
myermian
  • 31,823
  • 24
  • 123
  • 215
  • ICommand is also not working. Throws error before it reaches to ICommand method. – Pratik Aug 03 '14 at 14:12
  • @Pratik: You don't bind an `ICommand` directly to an event, you use the **Event To Command** pattern. – myermian Aug 03 '14 at 14:13
  • Can u please give an example? As I am beginner its a bit confusing for me. – Pratik Aug 03 '14 at 14:15
  • @m-y - What makes you think binding ItemsSource make it's binding mode `OneTime`? – Rohit Vats Aug 03 '14 at 14:17
  • @RohitVats: It doesn't, which is why I stated that if he wants to, he can use that setting. – myermian Aug 03 '14 at 14:18
  • @Pratik: There are too many variations of the **Event To Command** pattern, simply google it and you'll find a ton of examples. But, as stated, do not go that route in your situation, instead just bind your collection directly to the `ItemsSource`. – myermian Aug 03 '14 at 14:19
0

You cannot bind method to Loaded event in ViewModel. Move the event handler in code behind and change your XAML to this:

<ComboBox Name="Personnel_Combo" Loaded="Personnel_Combo_Loaded" 
          HorizontalAlignment="Left" Width="116"/>

Also accessing UI element in ViewModel is first and foremost violation of MVVM.


Moreover in loaded handler you are setting ItemSource, so get rid of Loaded handler and bind directly to the property in XAML:

<ComboBox Name="Personnel_Combo" ItemsSource="{Binding PersonnelName}" 
          HorizontalAlignment="Left" Width="116"/>

In case you intend to do much more in the event handler instead of setting ItemsSource, you have to create an ICommand in ViewModel and bind to the event using interactivity triggers. Check out the answer here to get you started on this.

Community
  • 1
  • 1
Rohit Vats
  • 79,502
  • 12
  • 161
  • 185
  • I wouldn't recommend code-behind if the *mvvm* tag exists. – myermian Aug 03 '14 at 14:08
  • m-y: U r correct. That was my reason. Anybody can you please show me solution maintaining MVVM? – Pratik Aug 03 '14 at 14:11
  • @m-y: MVVM never means no code behind. (If it's view specific thing then it's fine to have it in code behind) But in OP's case I also suggest solution for binding with ItemsSource. – Rohit Vats Aug 03 '14 at 14:16
  • @Rohit: In 2nd case, how can I bind the selected value of comboBox if I don't have such method with 'sender s' argument? – Pratik Aug 03 '14 at 14:17
  • @Pratik - You can bind `SelectedValue` directly like `ItemsSource`. Have some property in your class say `SelectedPerson` and bind from XAML like this `SelectedValue="{Binding SelectedPerson}"`. – Rohit Vats Aug 03 '14 at 14:19
  • Thanks Rohit. I applied as below. And But what could be the reason that it doesn't reflect after I select the value in data. – Pratik Aug 03 '14 at 14:33
  • Does setter of `PersonnelNameSelected` gets hit when you select value from comboBox and also from it's setter does you raise `PropertyChanged` event? – Rohit Vats Aug 03 '14 at 14:35
  • Yes even it sets in List as well – Pratik Aug 03 '14 at 14:37
  • Sry @RohitVats: It was my small mistake. Its done. Thanks. But I was worrying , is there really no way to do its with Load Method as I did in question? – Pratik Aug 03 '14 at 14:50
  • Like I mentioned you shouldn't access UI element from ViewModel (that's violation of MVVM). Keep UI access restricted to code behind only. – Rohit Vats Aug 03 '14 at 15:00
  • So the same method with'Sender s' argument we can not access in View-Model part. Am I right? – Pratik Aug 04 '14 at 00:52