juergen d
juergen d

Reputation: 204756

C#: Cast to Base

I have a DataGrid with a column that contains a Link. A file gets opened on click

<DataGridHyperlinkColumn Binding="{Binding Path=Number}" >
    <DataGridHyperlinkColumn.ElementStyle>
        <Style>
            <EventSetter Event="Hyperlink.Click" Handler="LinkClicked"/>
        </Style>
    </DataGridHyperlinkColumn.ElementStyle>
</DataGridHyperlinkColumn>

I use this method

public void LinkClicked(object sender, RoutedEventArgs e) 
{
    var vm = (BasePartViewModel<Part>) DataContext;
    vm.OpenFile();
}

I would like to use this code in my Base ViewModel class.

But the problem is that this cast does not work

(BasePartViewModel<Part>) DataContext

because actually for every implementation that is different. For instance

(BasePartViewModel<Plug>) DataContext

and Plug derives from Part. How to make it work without implementing this method in every derived ViewModel?

Upvotes: 0

Views: 91

Answers (2)

Steve
Steve

Reputation: 11963

you could factor out the OpenFile method into a covariant interface and then cast it to that interface.

interface MyInterface<out T>
{
    void OpenFile();
}

class Plug : Part
{ }


class Part
{ }

class BasePartViewModel<T> : MyInterface<T>
{
    public void OpenFile()
    {
        throw new NotImplementedException();
    }
}

class Program
{
    static void Main(string[] args)
    {
        BasePartViewModel<Plug> derived = new BasePartViewModel<Plug>();
        MyInterface<Part> b = derived;
        b.OpenFile();
    }
}

Upvotes: 1

Eyal Perry
Eyal Perry

Reputation: 2285

The solution to your problem is simple.
Put shortly, you've created a semi MVVM implementation.
When you go full MVVM, there's no need for code behind- and no need to cast a thing.

MVVM's answer to event handlers is the Command pattern.
(Plenty of articles lying around the WWW).

The simplest approach to implementing the Command pattern is rolling your own re-usable command class.
This should get you started- unless you are already using some kind of MVVM framework.
These usually come with their own set of implementations.

Once you've understood what the Command pattern is all about-
All you need to do is ensure that whichever ViewModel the view is bound to-
it has the expected command property exposed as a public property with a public getter.
This rids you of the need to have code in the xaml.cs file and rids you of casting.

There's an example of how to apply the Command Pattern to a DataGrid cell with a hyperlink here

Upvotes: 1

Related Questions