WPF 和 Prism - 绑定到模板选择器驱动的 ListBoxItem 的 IsSelected 事件未在 ViewModel 绑定代码中触发



我正在使用Prism和WPF。这是我的ViewModel:

using DialogueTool.Service.Abstracts;
using DialogueTool.Service.Models.Concretes;
using Prism.Commands;
using Prism.Mvvm;
using Prism.Regions;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
namespace DialogueTool.UI.ViewModels
{
public class DialogueEntryControlViewModel : BindableBase, INavigationAware
{
private IServices services;
private DialogueWrapperModel dialogueWrapperModel;
public DialogueEntryControlViewModel(IServices _services)
{
services = _services;
}
DialogueWrapperModel DialogueWrapperModel { get; set; }
public void OnNavigatedTo(NavigationContext navigationContext)
{
dialogueWrapperModel = navigationContext.Parameters.GetValue<DialogueWrapperModel>("DialogueWrapperModel");
DialogueEntries = new ObservableCollection<DialogueEntryModel>(dialogueWrapperModel.DialogueEntries);
}
public bool IsNavigationTarget(NavigationContext navigationContext)
{
//throw new NotImplementedException();
return true;
}
public void OnNavigatedFrom(NavigationContext navigationContext)
{
//throw new NotImplementedException();
}
#region Properties
private ObservableCollection<DialogueEntryModel> _breadCrumbs = new ObservableCollection<DialogueEntryModel>();
public ObservableCollection<DialogueEntryModel> BreadCrumbs
{
get { return _breadCrumbs; }
set { SetProperty(ref _breadCrumbs, value); }
}
/// <summary>
/// 
/// </summary>
public ObservableCollection<DialogueEntryModel> _dialogueEntries = new ObservableCollection<DialogueEntryModel>();
public ObservableCollection<DialogueEntryModel> DialogueEntries
{
get { return _dialogueEntries; }
set{ SetProperty(ref _dialogueEntries, value); }
}
private DialogueEntryModel _selectedDialogueEntry;
public DialogueEntryModel SelectedDialogueEntry
{
get { return _selectedDialogueEntry; }
set { SetProperty(ref _selectedDialogueEntry, value); }
}
private DialogueEntryModel _selectedDialogueEntryChoice;
public DialogueEntryModel SelectedDialogueEntryChoice
{
get { return _selectedDialogueEntryChoice; }
set { 
SetProperty(ref _selectedDialogueEntryChoice, value);
BreadCrumbs.Add(value);
}
}
#endregion
#region Commands
#endregion
}
}

这是我的xaml:

<UserControl x:Class="DialogueTool.UI.Views.Controls.DialogueEntryControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"
xmlns:templateSelector="clr-namespace:DialogueTool.UI.DataTemplateSelectors">
<UserControl.Resources>
<DataTemplate x:Key="QuestionDataTemplateTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Grid.Column="0"
Grid.Row="0"
TextWrapping="Wrap"
VerticalAlignment="Center"
Text="{Binding Text, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"></TextBlock>
<TextBlock Grid.Column="1"
Grid.Row="0"
FontSize="25"
FontWeight="Bold"
VerticalAlignment="Center">&#x21E9;</TextBlock>
<TreeView Grid.ColumnSpan="2"
Grid.Column="0"
Grid.Row="1"
Visibility="{Binding Path=DialogueEntries, Converter={StaticResource EmptyListToVisibilityConverter} }">
<TreeViewItem Header="Choices"
IsExpanded="{Binding Path=DialogueEntries, Converter={StaticResource EmptyListToBoolConverter} }">
<StackPanel Width="160">
<!--<Label>Search</Label>
<TextBox Text="{Binding ChapterSearchText, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" />-->
<!---->
<Label>Choices</Label>
<ListBox ItemsSource="{Binding DialogueEntries}"
SelectedItem="{Binding Path=SelectedDialogueEntryChoice, Mode=TwoWay}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Width="146">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Grid.Column="0"
Grid.Row="0"
MaxWidth="150"
TextWrapping="Wrap"
VerticalAlignment="Center"
Text="{Binding Text, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"></TextBlock>
<TextBlock Grid.Column="1"
Grid.Row="0"
FontSize="25"
FontWeight="Bold"
VerticalAlignment="Center">&#x21E8;</TextBlock>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</TreeViewItem>
</TreeView>
</Grid>
</DataTemplate>
<DataTemplate x:Key="TextDataTemplateTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Grid.Column="0"
Grid.Row="0"
TextWrapping="Wrap"
VerticalAlignment="Center"
Text="{Binding Text, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"></TextBlock>
<TextBlock Grid.Column="1"
Grid.Row="0"
FontSize="25"
FontWeight="Bold"
VerticalAlignment="Center">&#x21E9;</TextBlock>
</Grid>
</DataTemplate>
<templateSelector:DialogueEntryDataTemplateSelector x:Key="DialogueEntryDataTemplateSelector"
x:Name="DialogueEntryDataTemplateSelector"
TextTemplate="{StaticResource TextDataTemplateTemplate}"
QuestionTemplate="{StaticResource QuestionDataTemplateTemplate}" />
</UserControl.Resources>
<StackPanel>
<StackPanel FlowDirection="LeftToRight"
Orientation="Horizontal">
<ItemsControl ItemsSource="{Binding BreadCrumbs}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Excerpt}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
<!---->
<Label>Dialogue Entries</Label>
<ListBox ItemsSource="{Binding DialogueEntries}"
SelectedItem="{Binding SelectedDialogueEntry, Mode=TwoWay}"
ItemTemplateSelector="{StaticResource DialogueEntryDataTemplateSelector}">
</ListBox>
</StackPanel>
</UserControl>

以下到SelectedDialogueEntryChoice的绑定未触发ViewModel的SelectedDialogueEntryChoice属性:

<ListBox ItemsSource="{Binding DialogueEntries}"
SelectedItem="{Binding Path=SelectedDialogueEntryChoice, Mode=TwoWay}">

我读到树可能正在吸收点击事件,但我还没有弄清楚如何确保所选项目事件在中工作

为了确保我不会错过任何可能重要的东西,下面是我正在使用的DataTemplateSelector类:

using DialogueTool.Domain.Enums;
using DialogueTool.Service.Models.Concretes;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
namespace DialogueTool.UI.DataTemplateSelectors
{
public class DialogueEntryDataTemplateSelector : DataTemplateSelector
{
public DataTemplate QuestionTemplate { get; set; }
public DataTemplate TextTemplate { get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
var dialogueEntryModel = item as DialogueEntryModel;
switch (dialogueEntryModel.Type)
{
case DialogueEntryType.Question:
return QuestionTemplate;
case DialogueEntryType.Text:
return TextTemplate;
default:
return TextTemplate;
}
}
}
}

对评论中问题的回答:

Q:"不触发属性"是什么意思
A:当所选项目发生更改时,不会触发以下设置方法。

private DialogueEntryModel _selectedDialogueEntryChoice;
public DialogueEntryModel SelectedDialogueEntryChoice
{
get { return _selectedDialogueEntryChoice; }
set { 
SetProperty(ref _selectedDialogueEntryChoice, value);
BreadCrumbs.Add(value);
}
}

举个例子,SelectedDialogueEntryset方法确实会触发

我正在尝试的事情:

我已经尝试绑定到我的Xaml的UserControl元素,我希望它可以访问DataContext,从而访问我的ViewModel。。。但无济于事:

<ListBox ItemsSource="{Binding DialogueEntries}"
SelectedItem="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=SelectedDialogueEntryChoice}">

我发现的事情:

如果我从模板选择器中取出代码,SelectedDialogueEntryChoice就会起作用。所以我认为这是因为它无法访问ViewModel

诀窍是直接绑定到DataContext。我还需要找到DataContext所绑定的UserControlAncestorType

<ListBox ItemsSource="{Binding DialogueEntries}"
SelectedItem="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.SelectedDialogueEntryChoice, Mode=TwoWay}">

相关内容

  • 没有找到相关文章

最新更新