0
votes

When I am setting a property of my ViewModel (by that, I mean the class that implements INotifyPropertyChanged and is the DataContext of the view), OnPropertyChange is called but it just skips over "handler(this, new PropertyChangedEventArgs(name)" because PropertyChanged is null, therefore the UI is not updating. Below is my code:

XAML:

<Window x:Class="Magic_Vehicle_Portal_MVVM.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:Magic_Vehicle_Portal_MVVM"
    xmlns:vehicle="clr-namespace:Magic_Vehicle_Portal_MVVM.Vehicle"
    Title="MainWindow" Height="600" Width="800"
    >
<Grid >
    <Grid.DataContext>
        <vehicle:VehicleBase />
    </Grid.DataContext>
    <Grid.Resources>
        <Style x:Key="textBlockStyle"
               TargetType="TextBlock">
            <Setter Property="VerticalAlignment"
                    Value="Center" />
        </Style>
        <Style x:Key="textBoxStyle"
               TargetType="TextBox">
            <Setter Property="VerticalAlignment"
                    Value="Center" />
            <Setter Property="HorizontalAlignment"
                    Value="Left" />
            <Setter Property="Height"
                    Value="22" />
            <Setter Property="Width"
                    Value="200" />
        </Style>
        <Style x:Key="comboBoxStyle"
               TargetType="ComboBox">
            <Setter Property="VerticalAlignment"
                    Value="Center" />
            <Setter Property="HorizontalAlignment"
                    Value="Left" />

            <Setter Property="Height"
                    Value="22" />
            <Setter Property="Width"
                    Value="200" />
        </Style>
        <Style x:Key="datePickerStyle"
               TargetType="DatePicker">
            <Setter Property="VerticalAlignment"
                    Value="Center" />
            <Setter Property="HorizontalAlignment"
                    Value="Left" />
            <!--<Setter Property=""
                        Value="" />-->
            <Setter Property="Height"
                    Value="24" />
            <Setter Property="Width"
                    Value="200" />
        </Style>
     </Grid.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="30" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <Grid Grid.Row="0">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="2*" />
                <ColumnDefinition Width="2*" />
                <ColumnDefinition Width="160" />
            </Grid.ColumnDefinitions>
            <TextBlock Grid.Column="0"
                       Style="{StaticResource ResourceKey=textBlockStyle}" 
                       Text="Product Type"
                       Margin="10,2,0,0"/>
            <ComboBox Grid.Column="1"
                       Name="prodcutTypeTextblock"
                       Style="{StaticResource ResourceKey=comboBoxStyle}"
                       Margin="10,2,0,0"
                       ItemsSource="{Binding Path=Product_Type_List}"
                       Text="{Binding Path=Product_Type}" />
            <TextBox Grid.Column="2"
                     Name="searchKeyWordBox"
                     Style="{StaticResource ResourceKey=textBoxStyle}" 
                     HorizontalAlignment="Right"/>
            <Button Grid.Column="3"
                    Content="Search"
                    Width="120"
                    Height="22"
                    Margin="10,2,0,2"
                    HorizontalAlignment="Left"
                    Click="Search_Click"
                    IsDefault="True" />
        </Grid>
        <Grid Grid.Row="1">
            <Grid.RowDefinitions>
                <RowDefinition Height="40" />
                <RowDefinition Height="40" />
                <RowDefinition Height="40" />
                <RowDefinition Height="40" />
                <RowDefinition Height="40" />
                <RowDefinition Height="40" />
                <RowDefinition Height="40" />
                <RowDefinition Height="40" />
                <RowDefinition Height="40" />
                <RowDefinition Height="40" />
                <RowDefinition Height="40" />
                <RowDefinition Height="40" />
                <RowDefinition Height="40" />
                <RowDefinition Height="40" />
                <RowDefinition Height="40" />
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="20" />
                <ColumnDefinition Width="120" />
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="120" />
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="20" />
            </Grid.ColumnDefinitions>
            <TextBlock Grid.Column="1"
                       Grid.Row="0"
                       Text="Name"
                       Style="{StaticResource ResourceKey=textBlockStyle}"
                       FontWeight="Bold" />
            <TextBox Grid.Column="2"
                     Grid.ColumnSpan="3"
                     Grid.Row="0"
                     Width="565"
                     Style="{StaticResource ResourceKey=textBoxStyle}"
                     Text="{Binding Path=Vehicle_Name}" />
            <TextBlock Grid.Column="1"
                       Grid.Row="1"
                       Text="Onshore"
                       Style="{StaticResource ResourceKey=textBlockStyle}" />
            <CheckBox Grid.Column="2"
                      Grid.Row="1"
                      Content=""
                      VerticalAlignment="Center"
                      HorizontalAlignment="Left" />
            <TextBlock Grid.Column="1"
                       Grid.Row="2"
                       Text="Currency"
                       Style="{StaticResource ResourceKey=textBlockStyle}" />
            <ComboBox Grid.Column="2"
                      Grid.Row="2"
                      Style="{StaticResource ResourceKey=comboBoxStyle}"
                      ItemsSource="{Binding Path=Currency_List}"
                      SelectedItem="{Binding Path=Currency}" />
            <TextBlock Grid.Column="1"
                       Grid.Row="3"
                       Text="CUSIP"
                       Style="{StaticResource ResourceKey=textBlockStyle}" />
            <TextBox Grid.Column="2"
                     Grid.Row="3"
                     Style="{StaticResource ResourceKey=textBoxStyle}"
                     Text="{Binding Path=CUSIP}" />
            <TextBlock Grid.Column="1"
                       Grid.Row="4"
                       Text="ISIN"
                       Style="{StaticResource ResourceKey=textBlockStyle}" />
            <TextBox Grid.Column="2"
                     Grid.Row="4"
                     Style="{StaticResource ResourceKey=textBoxStyle}"
                     Text="{Binding Path=ISIN}" />
            <TextBlock Grid.Column="1"
                       Grid.Row="5"
                       Text="Ticker"
                       Style="{StaticResource ResourceKey=textBlockStyle}" />
            <TextBox Grid.Column="2"
                     Grid.Row="5"
                     Style="{StaticResource ResourceKey=textBoxStyle}"
                     Text="{Binding Path=Ticker}" />
            <TextBlock Grid.Column="1"
                       Grid.Row="6"
                       Text="Valoren"
                       Style="{StaticResource ResourceKey=textBlockStyle}" />
            <TextBox Grid.Column="2"
                     Grid.Row="6"
                     Style="{StaticResource ResourceKey=textBoxStyle}"
                     Text="{Binding Path=Valoren}" />
            <TextBlock Grid.Column="1"
                       Grid.Row="7"
                       Text="SAC Class"
                       Style="{StaticResource ResourceKey=textBlockStyle}" />
            <ComboBox Grid.Column="2"
                      Grid.Row="7"
                      Style="{StaticResource ResourceKey=comboBoxStyle}" />
            <TextBlock Grid.Column="1"
                       Grid.Row="8"
                       Text="PC Class"
                       Style="{StaticResource ResourceKey=textBlockStyle}" />
            <ComboBox Grid.Column="2"
                      Grid.Row="8"
                      Style="{StaticResource ResourceKey=comboBoxStyle}"
                      ItemsSource="{Binding Path=PC_Class_List}"
                      SelectedItem="{Binding Path=PC_Class}" />
            <TextBlock Grid.Column="1"
                       Grid.Row="9"
                       Text="Implementation Type"
                       Style="{StaticResource ResourceKey=textBlockStyle}" />
            <ComboBox Grid.Column="2"
                      Grid.Row="9"
                      Style="{StaticResource ResourceKey=comboBoxStyle}"
                      ItemsSource="{Binding Path=Implementation_Type_List}"
                      SelectedItem="{Binding Path=Implementation_Type}" />
            <ContentControl Grid.Row="1"
        </Grid>

    </Grid>

</Grid>

MainWindow:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private VehicleBase _selected_vehicle = new VehicleBase();
    public VehicleBase Selected_Vehicle
    {
        get
        {
            return _selected_vehicle;
        }
        set
        {
            _selected_vehicle = value;
        }
    }

    private void Search_Click(object sender, RoutedEventArgs e)
    {
        string keyword = searchKeyWordBox.Text;
        //int vehicle_id;
        string query;
        DataView dv;

        query = string.Format("select * from dbo.vehicle_attributes where vehicle_id = '{0}'",keyword);

        dv = Utility.DAL.ExecuteQuery(query);
        Selected_Vehicle.Vehicle_Name = dv[0]["vehicle_name"].ToString();
        Selected_Vehicle.OnPropertyChanged("Vehicle_Name");
        //vehicleSearchResults.ItemsSource = dv;
        //statusTextBlock.Text = string.Format("{0} Vehicle(s) Found", dv.Count);
    }
}

ViewModel:

public class VehicleBase: INotifyPropertyChanged 
    {
        public VehicleBase()
        {
            //Product_Type = product_type;
            SetLists();
            Product_Type = "Structure";
        }


        private void SetLists()
        {
            SetList_Product_Type();
            SetList_Currency();
            SetList_PC_Class();
        }



        public event PropertyChangedEventHandler PropertyChanged;

        public void OnPropertyChanged(string name)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(name));
            }
        }


        //ProductType
        private List<string> _product_Type_List = new List<string>();
        public List<string> Product_Type_List
        {
            get
            {
                return _product_Type_List;
            }
            set
            {
                _product_Type_List = value;
                OnPropertyChanged("Product_Type_List");
            }
        }
        private void SetList_Product_Type()
        {
            string query = "SELECT * FROM dbo.product_types WHERE is_enabled = 1";
            DataView dv = Utility.DAL.ExecuteQuery(query);
            List<string> l = new List<string>();
            for (int i = 0; i < dv.Count; i++)
            {
                l.Add(dv[i]["product_type_name"].ToString());
            }
            Product_Type_List = l;

        }

        private string _product_type;
        public string Product_Type
        {
            get
            {
                return _product_type;
            }
            set
            {
                _product_type = value;
                OnPropertyChanged("Product_Type");
            }
        }

        // Vehicle Name
        private string _vehicle_Name;
        public string Vehicle_Name
        {
            get
            {
                return _vehicle_Name;
            }
            set
            {
                _vehicle_Name = value;
                OnPropertyChanged("Vehicle_Name");

            }
        }
    }

ViewModel:

    <!-- language: c# -->

    public class VehicleBase: INotifyPropertyChanged 
    {
        public VehicleBase()
        {
            //Product_Type = product_type;
            SetLists();
            Product_Type = "Structure";
        }


        private void SetLists()
        {
            SetList_Product_Type();
            SetList_Currency();
            SetList_PC_Class();
        }



        public event PropertyChangedEventHandler PropertyChanged;

        public void OnPropertyChanged(string name)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(name));
            }
        }


        //ProductType
        private List<string> _product_Type_List = new List<string>();
        public List<string> Product_Type_List
        {
            get
            {
                return _product_Type_List;
            }
            set
            {
                _product_Type_List = value;
                OnPropertyChanged("Product_Type_List");
            }
        }
        private void SetList_Product_Type()
        {
            string query = "SELECT * FROM dbo.product_types WHERE is_enabled = 1";
            DataView dv = Utility.DAL.ExecuteQuery(query);
            List<string> l = new List<string>();
            for (int i = 0; i < dv.Count; i++)
            {
                l.Add(dv[i]["product_type_name"].ToString());
            }
            Product_Type_List = l;

        }

        private string _product_type;
        public string Product_Type
        {
            get
            {
                return _product_type;
            }
            set
            {
                _product_type = value;
                OnPropertyChanged("Product_Type");
            }
        }

        // Vehicle Name
        private string _vehicle_Name;
        public string Vehicle_Name
        {
            get
            {
                return _vehicle_Name;
            }
            set
            {
                _vehicle_Name = value;
                OnPropertyChanged("Vehicle_Name");

            }
        }
     }
2
You can't do that. You can't notify other ViewModels for you. Create a method on your SelectedVehicle and notify the properties you want from there.123 456 789 0

2 Answers

1
votes

DataContext Instance and Instance that is used in MainWindow.Xaml are different, PropertyChanged will be hooked only to the instance is bound to the UI. I think you done like this because you faced problem with Button click and faced issues in handling it in ViewModel, if that is the case, Implement ICommand in ViewModel to handle button click event, in that case all your code will be at one place, and it'll be easy for you to manipulate the data. Other wise you have to make your ViewModel SingleTon class and you have to use the same instance every where.

One more observation. Use observablecollection instead of List because List doesn't implement INotifyPropertyChanged, hence when you add new Item it'll not reflect in the UI where as observablecollection implements INotifyPropertyChanged

Refer the below links

http://www.c-sharpcorner.com/UploadFile/1a81c5/a-simple-wpf-application-implementing-mvvm/

http://www.c-sharpcorner.com/UploadFile/e06010/wpf-icommand-in-mvvm/

0
votes

You can change something like this in MainWindow.Xaml.cs as below

private VehicleBase _selected_vehicle = new VehicleBase();

public MainWindow()
{
    InitializeComponent();
    DataContext=_selected_vehicle;
}

and retain the remaining code as it is, no change is needed. Reomove the DataContext from your Xmal file. This will solve your issues no need to make the Viewmodel as SingleTon .

or if you want to set the dataContext only to the grid, then you can give a name to the grid say grid1 and set the dataContext as below instead of setting to entire window

public MainWindow()
{
    InitializeComponent();
    grid1.DataContext=_selected_vehicle;
}