我的问题是,即使触发PropertyChanged,UI也不会更新。 XAML:
<ListBox Name="BookShelf" Visibility="Hidden" SelectedItem="{Binding SelectedItem}" Panel.ZIndex="1" Height="Auto" Grid.Column="3" Margin="8,50,0,0" HorizontalAlignment="Center" ItemsSource="{Binding BookShelf}" Background="Transparent" Foreground="Transparent" BorderThickness="0" BorderBrush="#00000000">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel VerticalAlignment="Center" Orientation="Vertical">
<TextBlock FontSize="14" Margin="0,10,0,0" FontWeight="Bold" Foreground="Black" HorizontalAlignment="Center" Text="{Binding Path=DbId}" />
<TextBlock FontSize="16" FontWeight="Bold" Width="170" TextWrapping="Wrap" Foreground="Black" Margin="5" HorizontalAlignment="Center" Text="{Binding Path=DisplayName}" />
<Image HorizontalAlignment="Center" Source="{Binding Path=bookImage}" Width="200" Height="200" Margin="0,0,0,10" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
和
<ComboBox Margin="8,15,0,0" Name="bookShelf_ComboBox" ItemsSource="{Binding BookShelf}" SelectedItem="{Binding SelectedItem}" VerticalAlignment="Center" HorizontalAlignment="Center" DisplayMemberPath="DisplayName" Height="22" Width="140" Visibility="Visible" SelectionChanged="bookShelf_ComboBox_SelectionChanged"/>
视图模型:
public class BookShelfViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public event ShowContentInBrowser ShowDatabaseContent;
public BookShelfViewModel(ShowContentInBrowser showMethod)
{
ShowDatabaseContent += showMethod;
}
private ObservableCollection<DbInfo> _BookShelf = new ObservableCollection<DbInfo>();
public ObservableCollection<DbInfo> BookShelf
{
get
{
if (_BookShelf == null)
_BookShelf = new ObservableCollection<DbInfo>();
return _BookShelf;
}
set
{
if (value != _BookShelf)
_BookShelf = value;
}
}
private DbInfo _selectedItem { get; set; }
public DbInfo SelectedItem
{
get
{
return _selectedItem;
}
set
{
if (_selectedItem != value)
{
_selectedItem = value;
RaisePropertyChanged(new PropertyChangedEventArgs("SelectedItem"));
if (_selectedItem == null)
return;
if (_selectedItem.RelatedId != null)
ShowDatabaseContent(_selectedItem, _selectedItem.RelatedId);
else
ShowDatabaseContent(_selectedItem, _selectedItem.RelatedId);
}
}
}
public void RaisePropertyChanged(PropertyChangedEventArgs e)
{
if (PropertyChanged != null)
PropertyChanged(this, e);
}
}
我使用的代码用于设置DataContext和SelectedItem:
await System.Windows.Application.Current.Dispatcher.BeginInvoke(
DispatcherPriority.Background, new Action(
() => this.BookShelf.SelectedItem = dbInfo
)
);
和DataContext:
await System.Windows.Application.Current.Dispatcher.BeginInvoke(
DispatcherPriority.Background, new Action(
() => this.BookShelf.DataContext = bookShelfViewModel
)
);
我对这个MVVM设计很新,据我所知,我读过的文章中,我找不到什么错误。我猜测使用Dispatcher不是必要的,但在这种情况下我认为不重要...... ListBox确实显示了我的对象,但更新SelectedItem是这里的问题......
更新
继承我的DbInfo代码:
public class DbInfo
{
public int RelatedId { get; set; }
public string DbId { get; set; }
public TBase3.Article currentArticle { get; set; }
public string LinkId { get; set; }
public bool IsArticle { get; set; }
public string folder { get; set; }
public bool IsNamedArticle { get; set; }
public int currentBlockIndex { get; set; }
public int currentBlockCount { get; set; }
public string DisplayName { get; set; }
public int VScrollPos { get; set; }
public int THTextVersion { get; set; }
public bool isHtmlToc { get; set; }
public ImageSource bookImage { get; set; }
}
提醒我什么时候为ViewModel设置新值 - &gt; SelectedItem和它转到PropertyChanged(this,e);线。它没有选择在ListBox中选择DbInfo。
UPDATE2:
我的窗口右侧有一个书籍清单,就像书架上的许多书。 它显示所有带滚动的书。被选中的书的内容正在窗口中显示。 但是,如果有理由我想从代码隐藏更改为另一本书,它将内容更新为webbrowser但不更新ListBox某些书作为SelectedItem
ANSWER : 好的,我现在找到了答案。设置BookShelf.SelectedItem = dbInfo的代码应该是bookShelfViewModel.SelectedItem = bookShelfViewModel.BookShelf.First(x =&gt; x.DbId == dbInfo.DbIf);
答案 0 :(得分:2)
await System.Windows.Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() => this.BookShelf.DataContext = bookShelfViewModel));
看起来不太好,你在哪里这样做?我建议使用Galasoft MVVM Light和ViewModelLocator的用法来设置你的DataContext(通过nuget可用)。它为你提供了一个ViewModelBase,它具有你所有的属性需求和工作,你可以扩展到适合你的需要。听起来像DataContext,如果PropertyChanged甚至没有提出,可能是实际问题。
修改强>
As pointed out by Clemens the Mode=TwoWay in the binding is not needed here,因为它是SelectedItem
属性的默认值,我只是留下它作为示例....
<ComboBox Margin="8,15,0,0" Name="bookShelf_ComboBox" ItemsSource="{Binding BookShelf}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" VerticalAlignment="Center" HorizontalAlignment="Center" DisplayMemberPath="DisplayName" Height="22" Width="140" Visibility="Visible">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<command:EventToCommand Command="{Binding SelectedItemChangedCommand}" PassEventArgsToCommand="True"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ComboBox>
我注意到你的SelectionChanged =&#34; bookShelf_ComboBox_SelectionChanged&#34;在代码中,这是&#34; nasty&#34;,而是使用event to命令,因为你将viewmodel绑定到你的视图cbox。上面的代码将执行包含参数的命令,将以下内容添加到viewmodel。
public ICommand SelectedItemChangedCommand{ get; set;}
// somewhere in your code..
SelectedItemChangedCommand = new RelayCommand<SelectedItemChangedCommand>(OnSelectedItemChanged);
protected void OnSelectedItemChanged(SelectedItemChangedCommand e)
{
// Do your magic here! Or why not just call this method from the setter of your bound property?
}
The WPF Cheat Sheet 是一个很好的紧凑列表,包含所有类型的绑定,非常方便,我曾经在墙上和家里都有它,当我学习WPF时:)< / p>
希望有所帮助
干杯
了Stian
答案 1 :(得分:0)
UI的意思是不更新?你设置了一个新的ItemsSource并且没有看到任何改变?
如果是这种情况,请将您的财产更改为
public ObservableCollection<DbInfo> BookShelf
{
get
{
if (_BookShelf == null)
_BookShelf = new ObservableCollection<DbInfo>();
return _BookShelf;
}
set
{
if (value != _BookShelf)
{ _BookShelf = value;
RaisePropertyChanged(new PropertyChangedEventArgs("BookShelf"));
}
}
顺便说一句,我用另一种方式使用ObservableCollection。我只需初始化一次,然后使用Clear,Add,Remove。
如果ItemsSource不是您的问题,请发布DbInfo的代码,并为您的&#34;更新内容更新&#34;问题
答案 2 :(得分:0)
好的,我现在找到了答案。设置BookShelf.SelectedItem = dbInfo的代码应该是bookShelfViewModel.SelectedItem = bookShelfViewModel.BookShelf.First(x =&gt; x.DbId == dbInfo.DbIf);