1
votes

I have created an UserControl for reusability in my program:

GroupPanel.xaml:

  <UserControl x:Class="View.UserControls.GroupPanel"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"assembly=ViewModel"
             Name="root">
    <DockPanel>
        <DataGrid DockPanel.Dock="Top"
                  AutoGenerateColumns="False"
                  CanUserAddRows="True"
                  CanUserDeleteRows="False"
                  CanUserReorderColumns="False"
                  DataContext="{Binding ElementName=root}"
                  ItemsSource="{Binding DataGridItemSource}"
                  Name="mainGrid">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Nr/Unit"
                                    Binding="{Binding Nr}" />
                <DataGridTextColumn Header="Text"
                                    Binding="{Binding Text}" />
                <DataGridTextColumn Header="Comment"
                                    Binding="{Binding Comment}" />
                <DataGridTemplateColumn>
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <StackPanel Orientation="Horizontal">
                                <Button Content="Delete" />
                            </StackPanel>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
    </DockPanel>

and a Dependency Property to set the DataGrid's ItemsSource:

GroupPanel.xaml.cs:

public static readonly DependencyProperty DataGridItemSourceProperty =
        DependencyProperty.Register("DataGridItemSource", typeof(IEnumerable), typeof(GroupPanel),
                                    new PropertyMetadata(null));

    public IEnumerable DataGridItemSource
    {
      get { return (IEnumerable)GetValue(DataGridItemSourceProperty); }
      set { SetValue(DataGridItemSourceProperty, value); }
    }

I have a window where I need this UserControl 2 times with different ItemsSources to bind. But both Sources have the same properties up to first property. The sources are:

GroupNumber:
Number, int
Text, string
Comment, string

GroupUnit:
Unt, int
Text, string
Comment, string

The behaviour is the same for both of them. Is there a way to set the 1 DataGrid column's binding depending on the ItemsSource?

I have tried something like this:

    void GroupPanel_Loaded(object sender, RoutedEventArgs e)
    {
      var type = DataGridItemSource.GetType();
      if(type.FullName.Contains("GroupNumber"))
      {

      }
    }

But I don't know how to set the columns binding inside the if...

Thank you in advance

2
I suggest you to read about DataTemplate. You don't need an UserControl here, you can just define a Style for your DataGrid and reuse it. - dymanoid
WPF uses XAML and XAML is verbose... just get used to it. defining DataGrid columns programmatically is not the way to go. You'll often end up with duplicated sections of XAML, but believe me... you'll make it easier on yourself in the long run if you just accept that fact. It is possible though. See the DataGrid.AutoGeneratingColumn Event page on MSDN. - Sheridan

2 Answers

1
votes

You can add another dependecy property to your GroupPanel usercontrol:

public string FirstColumnBindingPropertyName
{
    get { return (string)GetValue(FirstColumnBindingPropertyNameProperty); }
    set { SetValue(FirstColumnBindingPropertyNameProperty, value); }
}

public static readonly DependencyProperty FirstColumnBindingPropertyNameProperty =
    DependencyProperty.Register("FirstColumnBindingPropertyName", typeof(string), typeof(GroupPanel), new UIPropertyMetadata(null, new PropertyChangedCallback(OnFirstColumnBindingPropertyNameChanged)));


private static void OnFirstColumnBindingPropertyNameChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args)
{
    GroupPanel groupPanel = (GroupPanel)dependencyObject;
    DataGridTextColumn dataGridTextColumn = groupPanel.mainGrid.Columns[0] as DataGridTextColumn;
    if (args.NewValue == null)
    {
        dataGridTextColumn.Binding = null;
    }
    else
    {
        dataGridTextColumn.Binding = new Binding(Convert.ToString(args.NewValue));
    }
}

Then in your window you will have:

<local:GroupPanel FirstColumnBindingPropertyName="Number" />
<local:GroupPanel FirstColumnBindingPropertyName="Unt" />
0
votes

You can use a DataTemplateSelector. Please refer below code.

<Window x:Class="DataTemplateSelector_Learning.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:DataTemplateSelector_Learning"
    Title="MainWindow" Height="350" Width="525">
<Window.Resources>
    <DataTemplate x:Key="GroupNumber">
        <TextBlock Text="{Binding Number}"/>
    </DataTemplate>
    <DataTemplate x:Key="GroupUnit">
        <TextBlock Text="{Binding Unit}" />
    </DataTemplate>
</Window.Resources>
<StackPanel>
    <DataGrid DockPanel.Dock="Top"
              AutoGenerateColumns="False"
              CanUserAddRows="False"
              CanUserDeleteRows="False"
              CanUserReorderColumns="False"                  
              Name="numGrid">
        <DataGrid.Columns>
            <DataGridTemplateColumn Header="GroupNumber">
                <DataGridTemplateColumn.CellTemplateSelector>
                    <local:GroupTemplateSelector 
                        GroupNumber="{StaticResource GroupNumber}"
                        GroupUnit="{StaticResource GroupUnit}"/>
                </DataGridTemplateColumn.CellTemplateSelector>
            </DataGridTemplateColumn>
            <DataGridTextColumn Header="Text"
                                Binding="{Binding Text}" />
            <DataGridTextColumn Header="Comment"
                                Binding="{Binding Comment}" />
            <DataGridTemplateColumn>
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <Button Content="Delete" />
                        </StackPanel>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
    </DataGrid>
    <DataGrid DockPanel.Dock="Top"
              AutoGenerateColumns="False"
              CanUserAddRows="False"
              CanUserDeleteRows="False"
              CanUserReorderColumns="False"                  
              Name="unitGrid">
        <DataGrid.Columns>
            <DataGridTemplateColumn Header="GroupUnit">
                <DataGridTemplateColumn.CellTemplateSelector>
                    <local:GroupTemplateSelector 
                        GroupNumber="{StaticResource GroupNumber}"
                        GroupUnit="{StaticResource GroupUnit}"/>
                </DataGridTemplateColumn.CellTemplateSelector>
            </DataGridTemplateColumn>
            <DataGridTextColumn Header="Text"
                                Binding="{Binding Text}" />
            <DataGridTextColumn Header="Comment"
                                Binding="{Binding Comment}" />
            <DataGridTemplateColumn>
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <Button Content="Delete" />
                        </StackPanel>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
    </DataGrid>
</StackPanel>

 public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        ObservableCollection<GroupNumber> lstNum = new ObservableCollection<GroupNumber>();
        lstNum.Add(new GroupNumber() { Number=1,Text="Test",Comment="Comment"});
        numGrid.ItemsSource = lstNum;
        ObservableCollection<Groupunit> lstUnit = new ObservableCollection<Groupunit>();
        lstUnit.Add(new Groupunit() { Unit = 2, Text = "Test", Comment = "Comment" });
        unitGrid.ItemsSource = lstUnit;
    }
}

public class GroupTemplateSelector : DataTemplateSelector
{
    public DataTemplate GroupNumber
    { get; set; }

    public DataTemplate GroupUnit
    { get; set; }

    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {            
        if (item is GroupNumber)
        {
            return GroupNumber;
        }
        else if (item is Groupunit)
        {
            return GroupUnit;
        }

        else
            return base.SelectTemplate(item, container);
    }

}

public class GroupNumber
{
    private int number;

    public int Number
    {
        get { return number; }
        set { number = value; }
    }

    private string text;

    public string Text
    {
        get { return text; }
        set { text = value; }
    }

    private string comment;

    public string Comment
    {
        get { return comment; }
        set { comment = value; }
    }      
}

public class Groupunit
{
    private int unit;

    public int Unit
    {
        get { return unit; }
        set { unit = value; }
    }

    private string text;

    public string Text
    {
        get { return text; }
        set { text = value; }
    }

    private string comment;

    public string Comment
    {
        get { return comment; }
        set { comment = value; }
    }
}