无法从Listvew.Resources内部访问viewmodel属性

时间:2010-12-03 18:24:02

标签: c# wpf mvvm mvvm-light

我正在尝试将SelectedItem绑定到View。但是当视图位于Resources块内时,视图无法访问viewmodel。 将datacontext重新分配给子项时,绑定适用于文本块,但不适用于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 个答案:

答案 0 :(得分:2)

更新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构造函数中添加它。更改ListView中的选择时,是否到达DataContextChangedHandler?

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由所有Childs继承,因此每个子节点都将以NoteViewModel作为DataContext结束。要将ListView用作Popup的DataContext,您可以执行此操作。我不确定StackPanel的DataContext绑定是做什么的,所以我可能会在这里遗漏一些东西..

<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 :(得分:1)

不使用直接插入NoteView并绑定DataContext,而是使用ContentPresenter:

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