WPF C# Data-binding to DataGridTextColumn
Asked Answered
H

4

22

I'm having a difficult time getting any data in this datagrid view to appear. I've followed some suggestions in a few other StackOverflow forum posts but am not having any luck getting the content to appear.

<DataGrid 
    x:Name="DataGridEmployees"
    DataContext="{Binding RelativeSource={RelativeSource AncestorType=Window}}"
    ItemsSource="{Binding GridView}"
    AutoGenerateColumns="True"
    Loaded="dataGrid1_Loaded"
    Margin="0,2,0,-2" Grid.ColumnSpan="2">
    <DataGrid.Columns>
        <DataGridTextColumn Header="EmployeeId" Width="175" Binding="{Binding Id}"></DataGridTextColumn>
        <DataGridTextColumn Header="Title" Width="175" Binding="{Binding Title}"></DataGridTextColumn>
        <DataGridTextColumn Header="WorkStatus" Width="175" Binding="{Binding WorkStatus}"></DataGridTextColumn>
        <DataGridTextColumn Header="FullName" Width="175" Binding="{Binding FullName}"></DataGridTextColumn>
    </DataGrid.Columns>
</DataGrid>

This is the click event that is being fired from a separate window (? could this be causing any problems?) in the xaml.cs file

public partial class MainMenu : Window
{
    WpfSampleEntities2 _context = new WpfSampleEntities2();

    public MainMenu()
    {
        InitializeComponent();
    }

    private void Button_Click_1(object sender, RoutedEventArgs e)
    {
        EmployeeDetails ed = new EmployeeDetails();
        ed.DataContext = ed.DomainEmployees;
        Binding bin = new Binding("GridView");
        bin.Source = ed.DomainEmployees;

        foreach (var item in ed.DomainEmployees)
        {
            bin.Path.PathParameters.Add(item);
        }

        ed.Show();
    }

}

And here is the EmployeeDetails.cs class/vm:

[TypeConverter(typeof(DataGridTextColumn))]
public class MVVMEmployee : Employee
{
    public int Id { get; set; }
    public string FullName { get; set; }
    public string Title { get; set; }
    public string WorkStatus { get; set; }

    public MVVMEmployee() { }
    public MVVMEmployee(int id, string fullName, string title, string workStatus)
    {
        this.Id = id;
        this.FullName = fullName;
        this.Title = title;
        this.WorkStatus = workStatus;
    }
}

I've also tried with the XAML as:

<DataGrid
    x:Name="DataGridEmployees"
    DataContext="{Binding RelativeSource={RelativeSource AncestorType=Window}}"
    ItemsSource="{Binding GridView}"
    AutoGenerateColumns="True"
    Loaded="dataGrid1_Loaded"
    Margin="0,2,0,-2" Grid.ColumnSpan="2">
    <DataGrid.Columns>
        <DataGridTextColumn Header="EmployeeId" Width="175" Binding="{Binding ElementName=Id}" ></DataGridTextColumn>
        <DataGridTextColumn Header="Title" Width="175" Binding="{Binding ElementName=Title}"></DataGridTextColumn>
        <DataGridTextColumn Header="WorkStatus" Width="175" Binding="{Binding ElementName=WorkStatus}"></DataGridTextColumn>
        <DataGridTextColumn Header="FullName" Width="175" Binding="{Binding ElementName=FullName}"></DataGridTextColumn>
    </DataGrid.Columns>
</DataGrid>
Heaviness answered 29/9, 2013 at 6:8 Comment(4)
I think you're setting the ItemsSource to a GridView property on your Window, does such a property exist?Clemmie
EmployeeDetails ed = new EmployeeDetails(); ed.DataContext = ed.DomainEmployees; .... here you are assigning the datacontext of ed with an item on ed? Is that right?Bathymetry
EmployeeDetails ed = new EmployeeDetails(); ed.DataContext = ed.DomainEmployees; DomainEmployees is the ObservableCollection of the viewmodel not a single item.Heaviness
I'm voting to close this question because the OP hasn't bothered to post the details of the exact issue they're having, it is an old question and doesn't have a proper answer, and the OP hasn't been seen since Dec 2013.Findlay
K
2

I would suggest to use the ICollectionView interface im my Window or better in my modelview class

Here is a example MainWindow.xaml.cs class, which demonstrates how to add data to such interface Class in via code-behind:

using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;
using System.Windows.Data;
using System.Windows.Input;

namespace WpfAppTest
{
    public partial class MainWindow : Window
    {
        public ICollectionView MyMVVMEmployeeList { get; private set; }

        public MainWindow()
        {
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            List<MVVMEmployee> list = new List<MVVMEmployee>();
            list.Add(new MVVMEmployee(23, "foomaster", "dr", "busy"));
            list.Add(new MVVMEmployee(42, "author", "mister", "dead"));

            MyMVVMEmployeeList = CollectionViewSource.GetDefaultView(list);

            //we call update gui //not needed when using modelview in pure mvvm 
            DataContext = this; 
        }
    }
}

The Binding in the MainWindow.xaml should then looks like:

<Window x:Class="WpfAppTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfAppTest"
        mc:Ignorable="d"
        DataContext="MainWindow"
        Title="MainWindow" Height="450" Width="800">
    <!-- for mvvm pattern using the model for datacontext deps e.g. like -->
    <!--  DataContext="{Binding Main,Source={StaticResource Locator}}"> -->
    <Grid>
        <StackPanel Orientation="Vertical">
            <DataGrid x:Name="DataGridEmployees"
                    ItemsSource="{Binding MyMVVMEmployeeList }"
                    AutoGenerateColumns="False">
                <DataGrid.Columns>
                    <DataGridTextColumn Header="EmployeeId" Width="175" Binding="{Binding Id}" ></DataGridTextColumn>
                    <DataGridTextColumn Header="Title" Width="175" Binding="{Binding Title}"></DataGridTextColumn>
                    <DataGridTextColumn Header="WorkStatus" Width="175" Binding="{Binding WorkStatus}"></DataGridTextColumn>
                    <DataGridTextColumn Header="FullName" Width="175" Binding="{Binding FullName}"></DataGridTextColumn>
                </DataGrid.Columns>
            </DataGrid>
            <Button Content="add" HorizontalAlignment="Left" Click="Button_Click"/>
        </StackPanel>
    </Grid>
</Window>

To make it fully runnable here your data class MVVMEmployee.cs again without refereing the base class:

namespace WpfAppTest
{
    public class MVVMEmployee 
    {
        public int Id { get; set; }
        public string FullName { get; set; }
        public string Title { get; set; }
        public string WorkStatus { get; set; }

        public MVVMEmployee() { }
        public MVVMEmployee(int id, string fullName, string title, string workStatus)
        {
            this.Id = id;
            this.FullName = fullName;
            this.Title = title;
            this.WorkStatus = workStatus;
        }
    }
}

Please change the namepspace WpfAppTest while including the example above. I would also suggest not use the code behind and use the MyMVVMEmployeeList the same way in your modelview class to follow more the mvvm pattern.

Kal answered 14/8, 2020 at 14:5 Comment(0)
B
0
myWindow w = new myWindow();
         w.DataContext = myViewModel;
         w.Show();

DataContext="{Binding RelativeSource={RelativeSource AncestorType=Window}}"

OR

<Window x:Name="MyWindow" />
    //DataGrid
    {Binding DataContext, ElementName=MyWindow}
    ItemsSource="{Binding MyViewModel.MyList}"
Bathymetry answered 29/9, 2013 at 17:16 Comment(0)
F
0

How you tried to implement it is simply not the way to go. First you need to separate the concerns and avoid mixing view and ViewModel. In the ViewModel create an ObservableCollection of your object (in your case MVVMEmployee ) which shall be implemented as a separate Model with NotifyPropertyChanged Event implemented and attached to your properties. Then simply create in your Window.cs constructor an instance of your ViewModel (let's call it vm) and set this.DataContext = vm; And then Bind the ItemsSource of the DataGrid to your collection from your viewModel like ItemsSource = {Binding MyEmployeesCollection} (no RelativeSource needed). Then bind each Text Column like i.e. Binding = {Binding FullName}. And don't forget to Implement INotifyPropertyChanged both on your model and on your ViewModel. That is one of the ways to implement your task in a clean MVVM manner. There are also other clean ways. I.e. You could Bind the DataContext to an instance of your ViewModel direct in the Window.xaml.

Fish answered 12/5, 2022 at 7:6 Comment(0)
M
0

Try adding Property to your View model With same property binding in your Xaml "GridView" then , this property Type should be Iobservablecollection that raises the RaisePropertyChanged() method Example :

        private ObservableCollection<Employee> _GridView = new 
        ObservableCollection<Employee>();
        public ObservableCollection<Employee> Publishers
        {
            get { return _GridView; }
            set { _GridView = value; RaisePropertyChanged(); }
        }

Please notice that you have to implement the INotifyPropertyChanged interface in you ViewModel and set the DataContext Of you View To your ViewModel like this :

ViewModel WM = new ViewModel ();
     this.DataContext = WM ;
Muss answered 18/5, 2022 at 16:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.