0

I have a class like:

class EditorViewModel
{
    public ObservableCollection<Effect> AllEffects;
    public bool HasPermissions;
}

But the problem is, when I am trying to bind AllEffects to ListView, then I can't bind anything to HasPermissions because the binding scope is limited to AllEffects, not EditorViewModel.

I tried this but it doesn't work:

<ListView ItemsSource="{Binding EditorViewModel}">

...

<GridViewColumn Width="Auto" Header="Name">
    <GridViewColumn.CellTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding AllEffects.Name}"/>
        </DataTemplate>
    </GridViewColumn.CellTemplate>
</GridViewColumn>

<GridViewColumn Width="Auto" Header="Type">
    <GridViewColumn.CellTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding AllEffects.Type}"/>
        </DataTemplate>
    </GridViewColumn.CellTemplate>
</GridViewColumn>

If I set the ItemsSource to EditorViewModel and get rid of AllEffects, it works. But then I don't know how to access HasPermissions through binding:

<GridViewColumn Width="50" Header="Override">
    <GridViewColumn.CellTemplate>
        <DataTemplate>
            <CheckBox Margin="0"
                                    HorizontalAlignment="Center"
                                    IsEnabled="{Binding HasPermission}"/>
        </DataTemplate>
    </GridViewColumn.CellTemplate>
</GridViewColumn>
Joan Venge
  • 315,713
  • 212
  • 479
  • 689

2 Answers2

2

As I updated my answer on this question to include, you can bind the ListView to the AllEffects property of your ViewModel and then refer to a different property of the ViewModel using a relative binding. So assuming your ListView is contained in a Window whose DataContext is an EditorViewModel, and the ListView's ItemsSource is AllEvents, you can still reference HasPermission like so:

<CheckBox Margin="0"
          HorizontalAlignment="Center"
          IsEnabled="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.HasPermission}"/>

That somewhat clunky notation will find the nearest parent element to the CheckBox in the visual tree that is of type Window, and bind to its DataContext property to find HasPermission.

Community
  • 1
  • 1
Dan J
  • 16,319
  • 7
  • 50
  • 82
  • Thanks, wow I am amazed. Is this how to do this? So it can't be done similar to the way I showed in my question? The reason I ask is if MS didn't think of these cases primarily? Or is this a corner case? Btw I am not critiquing your method, just trying to understand it. Thanks again. – Joan Venge Mar 16 '11 at 22:02
  • I tried your method but it says, path cannot be found in type RelativeSource. Is it because I have DataContext="{Binding RelativeSource={RelativeSource Self}}" at the top of the Window? – Joan Venge Mar 16 '11 at 22:05
  • MS really didn't think about MVVM too much when they implemented WPF to begin with.. it came afterwards :) only wpf/silverlight 5 would be targeted toward mvvm. – Elad Katz Mar 16 '11 at 22:06
  • I thought MS suggested everyone to use MVVM? What are you supposed to use it then, if not MVVM for WPF? Also WPF 5 is gonna handle all these stuff much easier and much better? – Joan Venge Mar 16 '11 at 22:11
  • 1
    MS are now suggesting that, but MVVM, as far as i know, didn't come from MS to begin with, but from the community. Power to the ppl! – Elad Katz Mar 16 '11 at 22:13
  • Also djacobson, you are missing a closing parenthesis, it doesn't compile so that could be it. – Joan Venge Mar 16 '11 at 22:14
  • Np man, appreciate your help. Never would have thought to use this myself. – Joan Venge Mar 16 '11 at 22:43
  • @Joan Venge It so happens I had to learn how this worked myself just the other day, so... Glad I could share the knowledge. :) – Dan J Mar 16 '11 at 22:45
  • @djacobson: btw I had a different question that's very similar. I was wondering if you would know this. This time instead of HasPermission, I am trying to bind to a collection in the same class, but after that I need to be able to bind to a specific property of the item stored in that collection. So like the collection is called GlobalSettings, and the properties inside each Setting type is .Name and .Value. – Joan Venge Mar 23 '11 at 22:26
  • I recommend asking a new question for that - I'm sure something like it has been answered before. :) – Dan J Mar 23 '11 at 23:08
1

A classic trick is to use ViewModelLocator, see: MVVM Light - using ViewModelLocator - properties hit multiple times

also, for a more quick-and-dirty solution, you can use the following Binding:

{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListView}, Path=DataContext.HasPermissions}

Note that this would only work on WPF and not in SL, since SL doesn't support this syntax of RelativeSource.

Community
  • 1
  • 1
Elad Katz
  • 7,483
  • 5
  • 35
  • 66
  • Thanks, I don't know how to use a ViewModelLocator. Seems pretty advanced, no? – Joan Venge Mar 16 '11 at 22:03
  • it's extremely simple actually.. just google it http://www.google.com/search?sourceid=chrome&ie=UTF-8&q=how+to+use+viewModelLocator – Elad Katz Mar 16 '11 at 22:05
  • Thanks, btw do you know why is it this complicated/involved? Because Locator sounds like something has to be located, but I already know where it is, if WPF had a way for me to just specify just like with single member data binding. – Joan Venge Mar 16 '11 at 22:07
  • you can also do it with RelativeSource Binding if you want. I'll update my answer. – Elad Katz Mar 16 '11 at 22:08
  • and now i see that @djacobson already answered that... +1 for him :) – Elad Katz Mar 16 '11 at 22:12
  • Thanks it works, but it says it cannot find that property on MainWindow. HasPermissions is on the class that's inside MainWindow, so like this: MainWindow has EditorViewModel (of type EditorViewModel) which has HasPermissions. Do you know if I can access this? – Joan Venge Mar 16 '11 at 22:18
  • yeah, look at my code i put in my answer, you look for the MainWindow using Relative Source, then in the Path u do Path=DataContext.HasPermissions (the DataContext is going to be your viewmodel in runtime). – Elad Katz Mar 16 '11 at 22:20
  • You are the man, it works. I had to do DataContext.EditorViewModel.HasPermissions after reading your comment. – Joan Venge Mar 16 '11 at 22:23
  • Btw do you know what this is called? Not ViewModelLocator, right? – Joan Venge Mar 16 '11 at 22:24
  • 1
    np :) i still suggest though that u try and learn about ViewModelLocator - it's a great pattern that I implement every time I do MVVM, and it has many benefits. – Elad Katz Mar 16 '11 at 22:24
  • Thanks Elad, will do. Do you use the ViewModelLocator even if you just wanted to do basic ItemsSource binding? If so then are you using it to work around the quirks of WPF? I thought WPF didn't have `any` quirks because MS thought it all out and learnt from previous mistakes. – Joan Venge Mar 16 '11 at 22:29
  • no, it's a general patterns that I use to connect the ViewModels to the Views, and to control the lifecycle of my ViewModels. It *also* solves your problem, but it's a great patten all-around. I never do MVVM without it – Elad Katz Mar 16 '11 at 22:32
  • Thanks Elad, will read more about it. ViewModelLocator just didn't seem like it's part of MVVM. – Joan Venge Mar 16 '11 at 22:34