WPF, calling method with parameters in XAML's class
-
09-10-2020 - |
Domanda
I have an ObjectDataProvider
in my XAML that references a method in my Window
-deriving class. That is, I have NewForm.xaml.cs
with class NewForm
and the ObjectDataProvider
in NewForm.xaml
is referencing a method in NewForm
. Currently, with the following XAML, I get a stack overflow error because the NewForm
constructor keeps getting called over and over again:
<Window x:Class="MyNamespace.NewForm" ...>
<Window.Resources>
<ObjectDataProvider x:Key="getTeamName"
ObjectType="{x:Type local:NewForm}"
MethodName="GetTeamName">
<ObjectDataProvider.MethodParameters>
<sys:Int32>-1</sys:Int32>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</Window.Resources>
</Window>
I'm guessing it's because the ObjectType
is set to NewForm
, so it loads NewForm
to load my application, but then it has to create a new instance of NewForm
in order to call GetTeamName
, but the constructor calls InitializeComponent
which creates a new NewForm
which has to create a new NewForm
to call GetTeamName
... It actually crashes Visual Studio 2010 every time.
Anyway, what I'm asking is do I have to define methods that my XAML calls via ObjectDataProvider
s in some other class? Or can I somehow use ObjectDataProvider
with a method defined in my XAML's class? Or to call a method in my XAML's class, should I be using some other XAML besides ObjectDataProvider
? It doesn't seem like I can put my C# method in another class since it uses TryFindResource
to get an XmlDataProvider
from my XAML.
Soluzione
The root of the problem here is that ObjectDataProvider
always creates a new instance of whatever object it's created for. So yes, it will create an instance of the NewForm
class, whose constructor will instantiate another ObjectDataProvider
that creates an instance of the NewForm
class, and then it's turtles all the way down.
But the thing is, ObjectDataProvider
is really just a way to declare create objects and call methods on them in XAML, so that you don't have to do it in code-behind. Since you're already creating the object in code-behind, avoiding code-behind isn't benefiting you. So just have the method that creates the object also add it to the window's resource dictionary:
// this method no longer needs to return anything, so you can change its signature
private void GetTeamName()
{
// code that creates the object goes here.
// and now, instead of "return myObject", do this:
Resources.Add("getTeamOName");
}