Arm0geddon
Arm0geddon

Reputation: 486

Value not being passed to UserControl for grid itemsource

I am trying to create a user control within a grid that takes one value and performs an action:

Grid:

<DataGrid x:Name="Grid1" CanUserAddRows="False" AutoGenerateColumns="False" 
            CanUserReorderColumns="False" CanUserResizeColumns="False" 
            CanUserResizeRows="False" 
            CanUserSortColumns="False" ScrollViewer.CanContentScroll="True" 
            SelectionUnit="Cell" 
            ClipboardCopyMode="None" HeadersVisibility="Column" 
            HorizontalScrollBarVisibility="Disabled"
            Width="1200" Height="150" BorderThickness="0" 
            GridLinesVisibility="None" BorderBrush="{x:Null}">
    <DataGrid.Resources>
        <Style TargetType="{x:Type DataGridCell}">
            <Setter Property="Foreground" Value="Black" />
            <Style.Triggers>
                <Trigger Property="IsSelected" Value="True">
                    <Setter Property="Background" Value="{x:Null}" />
                    <Setter Property="BorderBrush" Value="{x:Null}" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </DataGrid.Resources>
    <DataGrid.Background>
        <SolidColorBrush Color="White"/>
    </DataGrid.Background>
    <DataGrid.ItemBindingGroup>
        <BindingGroup/>
    </DataGrid.ItemBindingGroup>
    <DataGrid.Columns>
        <DataGridTemplateColumn CanUserResize="False" 
                                Header="Action Notes" 
                                IsReadOnly="True">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <local:ActionNotes WorkID="{Binding WorkID}">
                    </local:ActionNotes>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
    </DataGrid.Columns>
</DataGrid>

User Control Code:

public partial class ActionNotes : UserControl
{
    public static readonly DependencyProperty WorkIdDependency = 
    DependencyProperty.Register("WorkID", typeof(int), typeof(ActionNotes));

    public int WorkID
    {
        get { return (int)GetValue(WorkIdDependency); }
        set { SetValue(WorkIdDependency, value); }
    }

    public ActionNotes()
    {
        InitializeComponent();
        this.DataContext = this;

        MessageBox.Show(this.WorkID.ToString());
    }
}

But the MessageBox return WorkID as 0. I checked the item source, and it is passing the correct values to WorkID.

EDIT:

    public MainWindow()
    {
        InitializeComponent();

        List<DataItem1> test = new List<DataItem1>();
        test.Add(new DataItem1()
        {
            WorkID = 292
        });

        Grid1.ItemsSource = test;
    }

Upvotes: 0

Views: 133

Answers (3)

Walt Ritscher
Walt Ritscher

Reputation: 7037

I assume you calling MessageBox.Show() in the constructor of ActionNotes for debugging purposes, that you don't intend to leave that in production code. (:>)

Anyway, calling the MessageBox.Show method at the point in the constructor causes a System.InvalidOperationException to be thrown.

I believe that this exception is thrown to stop some tricky reentrancy problems with WPF.

Wrap the call to the Show method in Dispatcher.InvokeAsync to allow the Dispatcher to work around the issues. At this point, I'm able to see the WorkID value.

 public ActionNotes() {
      InitializeComponent();
      var x = this.WorkID.ToString();
      Dispatcher.InvokeAsync(() =>
      {
        MessageBox.Show(this.WorkID.ToString());
      });
}

Also, the values for WorkID are haven't been set yet in the constructor.

FWIW, you could debug this without the MessageBox, put a breakpoint in the constructor and evaluate this.WorkID in a Watch Window or Immediate Window.

Also you haven't shown the XAML for ActionNotes.

This bit of XAML is needed to see the value in ActionNotes.

<!-- in ActionNotes.xaml -->

Upvotes: 0

Adi Lester
Adi Lester

Reputation: 25201

Binding doesn't occur during the construction of your UserControl so WorkID won't be set at that stage, but only later. You can print your message from the Loaded event, at which stage the binding should have already happened. Also, you're changing the DataContext in your constructor, which is likely to cause problems, so simply remove it. Your constructor should then look like this:

public ActionNotes()
{
    InitializeComponent();

    Loaded += (sender, e) => MessageBox.Show(this.WorkID.ToString());
}

One more thing that is likely to cause problems is that your dependency property is not defined correctly. When defining a dependency property you must follow the "PropertyNameProperty" naming convention, and you should also be consistent with your property name (i.e. don't mix WorkId with WorkID)

So keeping these in mind, your property declaration should look like this:

public static readonly DependencyProperty WorkIDProperty = 
DependencyProperty.Register("WorkID", typeof(int), typeof(ActionNotes));

public int WorkID
{
    get { return (int)GetValue(WorkIDProperty); }
    set { SetValue(WorkIDProperty, value); }
}

Upvotes: 2

Dilmah
Dilmah

Reputation: 1127

I think value placed in Dependency property has string value for Integer Datatype that may be an issue.

Upvotes: 0

Related Questions