[英]WPF Binding with Notifyi does not update UI
我的問題是,即使觸發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-> SelectedItem設置新值,然后轉到PropertyChanged(this,e); 線。 它沒有選擇DbInfo作為在列表框中選擇。
更新2:
我在窗口的右邊有一個書單,就像一個書架里有很多書。 它顯示所有帶有滾動條的書。 窗口中顯示已選擇其內容的書。 但是,如果由於某種原因我想從代碼隱藏中切換到另一本書,它會將其內容更新為webbrowser而不是將特定書籍的ListBox更新為SelectedItem
答案 :好的,我現在找到了答案。 設置BookShelf.SelectedItem = dbInfo的代碼應該是bookShelfViewModel.SelectedItem = bookShelfViewModel.BookShelf.First(x => x.DbId == dbInfo.DbIf);
await System.Windows.Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() => this.BookShelf.DataContext = bookShelfViewModel));
看起來不好,您在哪里這樣做? 我建議使用Galasoft MVVM Light和ViewModelLocator來設置DataContext(可通過nuget訪問)。它為您提供了一個ViewModelBase,可以滿足您所有屬性的需求和工作,並且可以擴展以滿足您的需要。 聽起來像是DataContext,如果甚至沒有引發PropertyChanged,可能是實際的問題。
編輯:
正如Clemens所指出的,這里不需要綁定中的Mode = TwoWay ,因為無論如何它都是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 =“ bookShelf_ComboBox_SelectionChanged”,這很“討厭”,請改用event命令,因為您將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?
}
WPF備忘單是所有綁定類型的緊湊列表,非常方便,當我學習WPF時,我經常在牆上和家里都使用它:)
希望能幫助到你
干杯
施蒂安
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。 我只初始化一次,然后使用清除,添加,刪除。
如果ItemsSource不是您的問題,請發布DbInfo的代碼,並向您的“ UI未更新”問題寫更多內容
好吧,我現在找到了答案。 設置BookShelf.SelectedItem = dbInfo的代碼應該是bookShelfViewModel.SelectedItem = bookShelfViewModel.BookShelf.First(x => x.DbId == dbInfo.DbIf);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.