Невозможно получить доступ к свойствам viewmodel из Listvew.Resources - PullRequest
3 голосов
/ 03 декабря 2010

Я пытаюсь привязать выбранный элемент к представлению. Но представление не может получить доступ к модели представления, когда оно находится внутри блока ресурсов. При повторном назначении контекста данных дочерним элементам привязка работает для текстовых блоков, но не для UserControl (NoteView)

Мне не хватает привязки?

Пересмотренный (весь) код PFB и встроенные комментарии.

<UserControl x:Class="Konduva.View.NoteSearchView"
<!-- other namespaces here -->
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
DataContext="{Binding NoteSearch, Source={StaticResource Locator}}">
    <Grid>
    <ListView ItemsSource="{Binding Notes}"               
        SelectedItem="{Binding SelectedNote}">
        <ListView.Resources>
        <DataTemplate DataType="{x:Type vm:NoteViewModel}">
                    <DockPanel>
                        <TextBlock Text="{Binding Title}" />
                        <Popup Placement="Right"
                           PlacementTarget="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=ListViewItem}}"
                           IsOpen="{Binding (ListViewItem.IsSelected), RelativeSource={RelativeSource FindAncestor, AncestorType=ListViewItem}}"
                           DataContext="{Binding Path=DataContext, RelativeSource={RelativeSource AncestorType={x:Type ListView}}}">
                            <StackPanel>
  <!-- This is working -->      <TextBlock Text="{Binding SelectedNote.Title}" />
  <!-- This is not working -->  <v:NoteView DataContext="{Binding SelectedNote}" />                                
                            </StackPanel>
                        </Popup>
                    </DockPanel>
                </DataTemplate>
            </ListView.Resources>            
        </ListView>  
    </Grid>
</UserControl>

NoteView:

<Grid>
    <TextBlock Text="{Binding Title}" /> // This Text is not displayed
</Grid>

Ответы [ 2 ]

2 голосов
/ 14 декабря 2010

Обновление 3 Поскольку вы используете MvvmLight: в NoteView попробуйте изменить

DataContext="{Binding Note, Source={StaticResource Locator}}"

до

<UserControl.Style>
    <Style TargetType="UserControl">
        <Setter Property="DataContext" Value="{Binding Note, Source={StaticResource Locator}}"/>
    </Style>
</UserControl.Style>

Обновление 2

Обнаружил похожую проблему несколько минут назад, которую я не совсем понял, поэтому я добавлю здесь то же решение, чтобы посмотреть, поможет ли это. Что произойдет, если вы измените это на это?

<v:NoteView DataContext="{Binding RelativeSource={RelativeSource AncestorType={x:Type Popup}},
                                  Path=DataContext.SelectedNote}"/>

Обновление

Я не могу воспроизвести это. Попробуйте добавить это в свой конструктор NoteView. Вы достигаете DataContextChangedHandler, когда вы меняете выбор в ListView?

public NoteView()
{
    InitializeComponent();
    DependencyPropertyDescriptor dpd = 
        DependencyPropertyDescriptor.FromProperty(UserControl.DataContextProperty, 
                                                  typeof(UserControl));
    if (dpd != null)
    {
        dpd.AddValueChanged(this, new EventHandler(DataContextChangedHandler));
    }
}
void DataContextChangedHandler(object sender, EventArgs e)
{
    MessageBox.Show("DataContext Changed: " + DataContext);
}

Первый ответ

Ваша DockPanel получит NoteViewModel как DataContext, а не ListView, так как этот DataContext наследуется всеми дочерними объектами, каждый дочерний элемент получит NoteViewModel как DataContext. Чтобы использовать ListView в качестве DataContext для Popup, вы можете сделать это. Я не уверен, что делает привязка DataContext для StackPanel, поэтому я мог бы что-то здесь упустить ..

<DataTemplate DataType="{x:Type vm:NoteViewModel}">
    <DockPanel>
        <TextBlock Text="{Binding Title}" />
        <Popup Placement="Right" 
               PlacementTarget="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=ListViewItem}}" 
               IsOpen="{Binding (ListViewItem.IsSelected), RelativeSource={RelativeSource FindAncestor, AncestorType=ListViewItem}}"
               DataContext="{Binding Path=DataContext, RelativeSource={RelativeSource AncestorType={x:Type ListView}}}">
            <StackPanel>
                <TextBlock Text="{Binding SelectedNote.Title}" />
                <StackPanel>
                    <v:NoteView DataContext="{Binding SelectedNote}"/>
                </StackPanel>
            </StackPanel>
        </Popup>
    </DockPanel>
</DataTemplate>
1 голос
/ 04 декабря 2010

Вместо прямой вставки NoteView и привязки DataContext используйте ContentPresenter:

<ContentPresenter Content="{Binding SelectedNote}>
    <ContentPresenter.ContentTemplate>
       <DataTemplate>
           <v:NoteView />
       </DataTemplate>
   </ContentPresenter.ContentTemplate>
</ContentPresenter>
...