C# 与Notifyi的WPF绑定不会更新UI
我的问题是,即使触发PropertyChanged,UI也不会更新。 XAML: 和数据上下文:C# 与Notifyi的WPF绑定不会更新UI,c#,wpf,xaml,mvvm,inotifypropertychanged,C#,Wpf,Xaml,Mvvm,Inotifypropertychanged,我的问题是,即使触发PropertyChanged,UI也不会更新。 XAML: 和数据上下文: await System.Windows.Application.Current.Dispatcher.BeginInvoke( DispatcherPriority.Background, new Action( () => this.BookShelf.DataContext = bookShelfViewModel )
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(这个,e);线路。它没有选择在列表框中选择的DbInfo
更新2:
我在窗口的右边看到了一张书单,就像一个书架,里面有很多书。
它显示所有带卷轴的书。选择其内容的书籍将显示在窗口中。
但若出于某种原因,我想从代码隐藏改为另一本书,它会将其内容更新到webbrowser,但不会将该书的列表框更新为SelectedItem
回答:
好吧,我现在找到答案了。设置BookShelf.SelectedItem=dbInfo的代码应该是bookShelfViewModel.SelectedItem=bookShelfViewModel.BookShelf.First(x=>x.DbId==dbInfo.DbIf)
看起来不太好,你在哪里做的?我建议使用ViewModelLocator来设置DataContext(可通过nuget获得)。它为您提供了一个ViewModelBase,以及您所有的属性更改需求和工作,您可以扩展它以满足您的需求。听起来像是DataContext,如果PropertyChanged甚至没有被提出,这可能是实际的问题
编辑:
,因为它是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\u ComboBox\u SelectionChanged”,这是“讨厌的”,请改用event to命令,因为您正在将viewmodel绑定到views 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?
}
public ICommand选择editemchangedcommand{get;set;}
//在代码的某个地方。。
选择EditemChangedCommand=new RelayCommand(在SelectedItemChanged上);
SelectEditemChanged(SelectedItemChangedCommand e)上的受保护无效
{
//在这里施展你的魔法!或者为什么不直接从绑定属性的setter调用这个方法呢?
}
是一个很好的所有类型绑定的紧凑列表,非常方便,我在学习WPF时,在家里和墙上都有它:)
希望能有帮助
干杯
斯蒂安你所说的用户界面没有更新是什么意思?您设置了一个新的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"));
}
}
公共可观察收集书架
{
得到
{
if(_BookShelf==null)
_BookShelf=新的ObservableCollection();
归还书架;
}
设置
{
如果(值!=\u书架)
{{u BookShelf=value;
RaisePropertyChanged(新的属性更改开发标签(“书架”);
}
}
顺便说一句,我用另一种方式使用ObservableCollection。我只需初始化它一次,然后使用Clear、Add、Remove
如果项目资源不是您的问题,请发布DbInfo的代码,并在“UI未更新”问题中写入更多内容。好的,我现在找到了答案。设置BookShelf.SelectedItem=DbInfo的代码应该是bookShelfViewModel.SelectedItem=bookShelfViewModel.BookShelf.First(x=>x.DbId==DbInfo.DbIf)是否检查了XAML上的绑定模式?如果从视图更新视图模型并从视图更新视图,则需要使用双向模式model@aggietech您的意思是SelectedItem绑定?默认情况下,该属性是双向绑定的。bookShelf\u ComboBox\u SelectionChanged没有触发任何操作,对吗?您正在尝试若要获取“SelectionChanged”事件以在视图模型中触发命令?具体如何定义DataContext?如果您确定引发了PropertyChanged事件,但UI未更新,我认为DataContext设置不正确。@Jon Koivula有人问了与您相同的问题(至少在同一时间),我给出了一个示例解决方案,如果您愿意,请检查它并将其应用于您的模型。默认情况下WPF不是双向绑定吗?Silverlight是单向的-这让我多次困惑…无论如何,最安全的方法是始终指定它explicitly@sondergard不,默认值是单向的,就像SL=)@Stian一样。这是错误的。一些依赖属性绑定双向默认情况下。例如SelectedItem有。请查看依赖项属性信息。@Clemens-Hmm我实际上没有意识到这一点,发现了另一个WPF异常;)您完全正确+1不是一个异常,只是一个功能。如果您仔细想想,它非常有意义。列表框显示了我的ObservableCollection拥有的所有项,但它没有选择在列表框中选择该项,无论其值是多少BookShelfViewModel.SelectedItem。除非单击列表框中的项,否则它只会被选中,而不会被代码隐藏
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; }
}
await System.Windows.Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() => this.BookShelf.DataContext = bookShelfViewModel));
<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>
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?
}
public ObservableCollection<DbInfo> BookShelf
{
get
{
if (_BookShelf == null)
_BookShelf = new ObservableCollection<DbInfo>();
return _BookShelf;
}
set
{
if (value != _BookShelf)
{ _BookShelf = value;
RaisePropertyChanged(new PropertyChangedEventArgs("BookShelf"));
}
}