tags:

views:

18

answers:

1

In my list view control (or any other WPF control that will fit the situation), I would like to have one TextBlock that stays consistent for all items while another TextBlock that changes based on the value in the ObservableCollection. Here is how my code is currently laid out:

XAML

       <ListView ItemsSource="{Binding Path=MyItems, Mode=TwoWay}">      
            <ListView.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock x:Name="StrVal" Text="{Binding StrVal}" />         
                        <TextBlock x:Name="ConstVal" Text="{Binding MyVM.ConstVal, Mode=TwoWay}" />
                    </StackPanel>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>

Model

 public class MyItem
    {
        public string StrVal { get; set; }        
    }

ViewModel

public MyVM()
{

    ObservableCollection<MyItem> myItems = new ObservableCollection<MyItem>();
    for (int i = 0 ; i < 10; i++)            
        myItems.Add(new MyItem { StrVal = i.ToString()});

    MyItems = myItems;
    ConstVal = "1";
}

private string _constVal;
public string ConstVal
{
    get
    {
        return _constVal;
    }
    set
    {
        _constVal = value;
        OnPropertyChanged("ConstVal");
    }
}
public ObservableCollection<MyItem> MyItems { get; set; }

public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string item)
{
    if (PropertyChanged != null)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(item));
    }
}

}

Code Behind

this.DataContext = new MyVM();

The StrVal property repeats correctly in the ListView, but the ConstVal TextBlock does not show the ConstVal that is contained in the VM. I would guess that this is because the ItemsSource of the ListView is MyItems and I can't reference other variables outside of what is contained in the MyItems.

My question is: How do I get ConstVal to show the value in the ViewModel for all listviewitems that will be controlled by the Observable Collection of MyItems.

+1  A: 

There are 2 ways I can see to do this.

1) you can name the usercontrol that you are within (x:Name=control or whatever) and then do.

<TextBlock x:Name="ConstVal" Text="{Binding ElementName=control, Path= DataContext.ConstVal, Mode=TwoWay}" />

2) use relative source:

    <TextBlock x:Name="ConstVal" Text="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListView}}, Path=DataContext.ConstVal, Mode=TwoWay}" />

EDIT:

3) Because of the way that you are nesting your items (i.e. with no new datacontexts being introduced you can simply do:

<TextBlock x:Name="ConstVal" Text="{Binding Path=DataContext.ConstVal, Mode=TwoWay}" />
Leom Burke
Thanks! The relative source answer seems more robust, since it's not dependent upon the name of the user control which could change. I appreciate your help!
Blake Blackwell
Yes - I have used both in my controls - if I need to access the VM multiple times in the same way it can become tedious to keep doing the relative source way.
Leom Burke
I have just relaised something about the way you are doing this that allows you to use a simpler approach - edit coming up....
Leom Burke