将listbox项中的命令绑定到viewmodel parent上的属性

gid*_*eon 20 wpf binding mvvm icommand

我一直在研究这个问题大约一个小时,并查看了所有相关的SO问题.

我的问题很简单:

我有HomePageVieModel:

HomePageVieModel
+IList<NewsItem> AllNewsItems
+ICommand OpenNews
Run Code Online (Sandbox Code Playgroud)

我的加价:

<Window DataContext="{Binding HomePageViewModel../>
<ListBox ItemsSource="{Binding Path=AllNewsItems}">
 <ListBox.ItemTemplate>
   <DataTemplate>
       <StackPanel>
        <TextBlock>
           <Hyperlink Command="{Binding Path=OpenNews}">
               <TextBlock Text="{Binding Path=NewsContent}" />
           </Hyperlink>
        </TextBlock>
      </StackPanel>
    </DataTemplate>
</ListBox.ItemTemplate>
Run Code Online (Sandbox Code Playgroud)

列表显示所有项目都很好,但对于我的生活,无论我尝试命令将无法工作:

<Hyperlink Command="{Binding Path=OpenNewsItem, RelativeSource={RelativeSource AncestorType=vm:HomePageViewModel, AncestorLevel=1}}">
<Hyperlink Command="{Binding Path=OpenNewsItem, RelativeSource={RelativeSource AncestorType=vm:HomePageViewModel,**Mode=FindAncestor}**}">
<Hyperlink Command="{Binding Path=OpenNewsItem, RelativeSource={RelativeSource AncestorType=vm:HomePageViewModel,**Mode=TemplatedParent}**}">
Run Code Online (Sandbox Code Playgroud)

我总是得到:

System.Windows.Data错误:4:无法找到带引用的绑定源.....

更新 我正在设置我的ViewModel吗?不认为这很重要:

 <Window.DataContext>
        <Binding Path="HomePage" Source="{StaticResource Locator}"/>
    </Window.DataContext>
Run Code Online (Sandbox Code Playgroud)

我使用MVVMLight工具包中的ViewModelLocator类来完成这项工作.

小智 31

稍微不同的例子但是,我发现通过在绑定中引用父容器(使用ElementName),您可以使用Path语法获取它的DataContext及其后续属性.如下所示:

<ItemsControl x:Name="lstDevices" ItemsSource="{Binding DeviceMappings}">
 <ItemsControl.ItemTemplate>
  <DataTemplate>
   <Grid>
    <ComboBox Text="{Binding Device}" ItemsSource="{Binding ElementName=lstDevices, Path=DataContext.AvailableDevices}" />
    ...
   </Grid>
  </DataTemplate>
 </ItemsControl.ItemTemplate>
</ItemsControl>
Run Code Online (Sandbox Code Playgroud)


Cam*_*and 13

这里有两个对你不利的问题.

DataContextDataTemplate被设置为模板显示的项目.这意味着您不能在不设置源的情况下使用绑定.

另一个问题是模板意味着该项在技术上不是逻辑树的一部分,因此您无法在DataTemplate节点之外搜索祖先.

要解决此问题,您需要将绑定范围扩展到逻辑树之外.您可以使用此处定义的DataContextSpy .

<ListBox ItemsSource="{Binding Path=AllNewsItems}">
    <ListBox.Resources>
        <l:DataContextSpy x:Key="dataContextSpy" />
    </ListBox.Resources>

    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <TextBlock>
                   <Hyperlink Command="{Binding Source={StaticResource dataContextSpy}, Path=DataContext.OpenNews}" CommandParameter="{Binding}">
                       <TextBlock Text="{Binding Path=NewsContent}" />
                   </Hyperlink>
               </TextBlock>
           </StackPanel>
       </DataTemplate>
   </ListBox.ItemTemplate>
</ListBox>
Run Code Online (Sandbox Code Playgroud)

  • +1谢谢!=)有点恼人的人需要一个解决方法吗?在WPF中,您希望将列表中的Child项绑定到某些父项,这是不是很常见!? (2认同)

Job*_*Joy 8

因此,您似乎正在尝试将适当的DataContext提供给HyperLink,以便触发ICommand.我认为简单的元素名称绑定可以解决这个问题.

<Window x:Name="window" DataContext="{Binding HomePageViewModel../>
 <ListBox ItemsSource="{Binding Path=AllNewsItems}">
 <ListBox.ItemTemplate>
  <DataTemplate>
   <StackPanel>
    <TextBlock>
       <Hyperlink DataContext="{Binding DataContext ,ElementName=window}" Command="{Binding Path=OpenNews}">
           <TextBlock Text="{Binding Path=NewsContent}" />
       </Hyperlink>
    </TextBlock>
  </StackPanel>
</DataTemplate>
Run Code Online (Sandbox Code Playgroud)

AncestorType仅检查Visual-Types而不检查ViewModel类型.


xtd*_*tds 6

尝试这样的事情

<Button Command="{Binding DataContext.YourCommand,RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}"
Run Code Online (Sandbox Code Playgroud)

他无法在列表框中找到您的命令绑定,因为您为该列表框设置了不同的datacontext而不是viewmodel