Question

My main goal right now is to use this syntax which I have seen in working code previously:

{Binding SelectedItem, ElementName=JobTest}

My current understanding of this code is that ElementName overrides the regular Binding convention of the "parent" Data Context and tells the binding to pull from whatever source the other element is. SelectedItem obviously just filters the source to the selected one.

I wanted to get something very simple working and decided to use two <ListView> Elements:

<ListView Name="JobTest" ItemsSource="{Binding JobsTest}" Grid.Column="2" />
<ListView ItemsSource="{Binding SelectedItem, ElementName=JobTest}" Grid.Column="3"/>

One with the regular Binding to an ObservableCollection the other just displaying the selected one from the first.

Here is the property I've set and used in the DataContext:

public ObservableCollection<JobViewModel> JobsTest { get; set; }

I set it here:

this.myContext.JobsTest = new ObservableCollection<JobViewModel>(data.JobModels.Select(jm => new JobViewModel(jm)));

The first List View IS populating with data, however, why is it that when I select an item from the first List View it is not displayed in the second? I'll be keeping an eye on this post and will be happy to oblige to any further code viewing requests. Thanks!

Was it helpful?

Solution

You cannot bind single item to list of items. Since, as you mentioned, JobViewModel

is just a class which has properties like Name, Description, Schedule among others

one way to do it is to use some sort of Grid or StackPanel to show fields of SelectedItem

<ListView Name="JobTest" ItemsSource="{Binding JobsTest}" Grid.Column="2" />
<StackPanel DataContext="{Binding SelectedItem, ElementName=JobTest}" Grid.Column="3">
    <TextBlock Text="{Binding Name}"/>
    <TextBlock Text="{Binding Description}"/>
    <TextBlock Text="{Binding Schedule}"/>
</StackPanel>

OTHER TIPS

In case the list view selection mode allows multiple selection and you need to have a way to bind SelectedItems to your view model, you will find that SelectedItems is readonly and not bindable. Below is one of the workaround using System.Windows.Interactivity and Microsoft.Expression.Interactions. If you need these, it can be download from here

Additional namespace declaration in XAML

xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"

XAML:

<ListView Name="JobTesList" ItemsSource="{Binding JobsTest}" DisplayMemberPath="Name"  Grid.Column="0">
  <i:Interaction.Triggers>
    <i:EventTrigger EventName="SelectionChanged">
      <ei:ChangePropertyAction TargetObject="{Binding Mode=OneWay}" PropertyName="SelectedItems" Value="{Binding Path=SelectedItems, ElementName=JobTesList}"/>
    </i:EventTrigger>
  </i:Interaction.Triggers>
</ListView>
<ListView ItemsSource="{Binding SelectedItems}" DisplayMemberPath="Name"  Grid.Column="1"/>

View Model:

public class JobViewModel
{
  public ObservableCollection<JobViewModel> JobsTest { get; set; }
  public ObservableCollection<JobViewModel> SelectedJobs { get; set; }

  public JobViewModel() {
    JobsTest = new ObservableCollection<JobViewModel>();
    SelectedJobs = new ObservableCollection<JobViewModel>();

  }

  public string Name {
    get;
    set;
  }

  public System.Collections.IList SelectedItems {
    get {
      return SelectedJobs;
    }
    set {
      SelectedJobs.Clear();
      foreach (JobViewModel model in value) {
       SelectedJobs.Add(model);
      }
    }
  }
}

In example above, your ViewModel will pick up the selected items whenever the selection on ListView changed.

The only way I've seen this to work is the following:

<ListView Name="JobTest" ItemsSource="{Binding JobsTest}" Grid.Column="2" />
<ListView ItemsSource="{Binding Path=DataContext.JobsTest, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" Grid.Column="3"/>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top