Jeff Dege Jeff Dege - 4 months ago 29
C# Question

Error: "This operation is valid only on elements that have this template applied"

I have a C# WPF application that contains a user control:

<UserControl
x:Name="payrollEntryControl"
x:Class="MyNamespace.PayrollEntryControl"
[...]
>
[...]
</UserControl>


Within the user control, I have a Telerik
RadDataForm
:

<telerik:RadDataForm
x:Name="payrollAddForm"
CurrentItem="[...]"
EditTemplate="{StaticResource myEditTemplate}"
/>


The template contains a Telerik
RadGridView
and a
Button
:

<telerik:RadGridView Grid.Row="0" Grid.Column="0"
x:Name="workGridView"
[...]
ItemsSource="{Binding [...]}"
>
<telerik:RadGridView.Columns>
[...]
</telerik:RadGridView.Columns>
</telerik:RadGridView>
<Button Grid.Row="1" Grid.Column="0"
Command="{Binding addWorkCommand, ElementName=payrollEntryControl}"
>
Add
</Button>


I want the command to do is call
BeginInsert()
on
workGridView
. But I can't seem to get access to
workGridView
.

My command, so far:

private DelegateCommand addWorkCommand_ = null;
public DelegateCommand addWorkCommand
{
get
{
if (this.addWorkCommand_ == null)
{
this.addWorkCommand_ = new DelegateCommand(
o => addWork(o)
);
}

return this.addWorkCommand_;
}
}

private void addWork(object o)
{
var addForm = this.payrollAddForm;
var editTemplate = addForm.EditTemplate;
var workGrid = editTemplate.FindName("workGridView", addForm);
}


My problem? When I make the call to
editTemplate.FindName()
, I get an exception:


This operation is valid only on elements that have this template applied.


I don't understand. I'm getting the template from the form. How can it not be applied?

Answer

Peter Duniho's comment pointed me to this answer, which addressed my problem.

This method will help you:

public T FindElementByName<T>(FrameworkElement element, string sChildName) where T : FrameworkElement
{
    T childElement = null;
    var nChildCount = VisualTreeHelper.GetChildrenCount(element);
    for (int i = 0; i < nChildCount; i++)
    {
        FrameworkElement child = VisualTreeHelper.GetChild(element, i) as FrameworkElement;

        if (child == null)
            continue;

        if (child is T && child.Name.Equals(sChildName))
        {
            childElement = (T)child;
            break;
        }

        childElement = FindElementByName<T>(child, sChildName);

        if (childElement != null)
            break;
    }

    return childElement;
}

And, how I use it, just add button, and on button Click:

private void Button_OnClick(object sender, RoutedEventArgs e)
{
    var element = FindElementByName<ComboBox>(ccBloodGroup, "cbBloodGroup");
}
 [1]: http://stackoverflow.com/a/19907800/243563

An alternative is to pass the workGridView as a CommandParameter:

<Button Grid.Row="1" Grid.Column="0"
    CommandParameter="{Binding ElementName=workGridView}"
    Command="{Binding addWorkCommand}" >
 ....

private void addWork(object o)
{
    RadGridView grid = o as RadGridView;
    grid.BeginInsert();
}
Comments