簡體   English   中英

使用Notifyi進行WPF綁定不會更新UI

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM