I use C# pattern matching often in my work, especially with the switch/case as illustrated in the example below. These work great and no issues here as long as the type is passed within the ViewModel as shown:
var fruit = new Apple();
MakePie(fruit);
.
private void MakePie(object fruit)
{
if (fruit != null)
{
Debug.WriteLine(fruit.GetType().Name);
switch (fruit)
{
case Apple _:
MakeApplePie();
break;
case Cherry _:
MakeCherryPie();
break;
}
}
}
However, I discovered that if I pass the type as a CommandArgument from XAML, the above switch/case will fail, even though the correct type is passed as the argument -- it just that the switch/case no longer evaluates correctly by C# pattern matching for some reason.
<Button Content="Make Apple Pie" CommandParameter="{x:Type models:Apple}" Command="{Binding MakePie}"/>
<Button Content="Make Cherry Pie" CommandParameter="{x:Type models:Cherry}" Command="{Binding MakePie}"/>
So just to perform a simple determination, I used this:
Debug.WriteLine(fruit.GetType().Name)
I was expecting to see either 'Apple' or 'Cherry', but instead, I got 'RuntimeType' as the name, even though I can clearly see from the fruit object that its type and type name match correctly to the 'Apple' or 'Cherry' classes from my models.
So can anyone explain or tell me if I am doing something wrong, or that I simply cannot pass the type from XAML to a switch/case pattern matching unless it is done from the ViewModel?
What would be the correct usage/implementation if you want to pass a type as a CommandArgument from XAML and also want the switch/case pattern matching to work?
To Amjad and dba:
Here, try the codes below on your end and let me know your results. Notice the private string TestSwitch(object t)
function/method takes an object t as the argument. You will see that the switch pattern matching works just fine with t being an object. This is how I have implemented this pattern numerous times in other applications, but have always done it inside the ViewModel. First time trying to do it in XAML (no changes other than where the type is passed), and it doesn't work, and I can't seem to figure out the reason.
public partial class MainWindow : Window
{
public class TestClass1
{
public int MyProperty1 { get; set; }
}
public class TestClass2
{
public string MyProperty2 { get; set; }
}
public class TestClass3
{
public string MyProperty3 { get; set; }
}
public MainWindow()
{
InitializeComponent();
var t1 = new TestClass1();
Debug.WriteLine(TestSwitch(t1));
var t2 = new TestClass2();
Debug.WriteLine(TestSwitch(t2));
var t3 = new TestClass3();
Debug.WriteLine(TestSwitch(t3));
}
private string TestSwitch(object t)
{
switch (t)
{
case TestClass1 _:
return "TestClass1";
case TestClass2 _:
return "TestClass2";
case TestClass3 _:
return "TestClass3";
}
return "??????";
}
}