[英]Binding with INotifyPropertyChanged Still Doesn't Work
嘗試了很多東西,仍然無法正常工作。 綁定兩個TextBlocks無效。 使用INotifyPropertyChanged
接口非常類似於此代碼 ,但無濟於事。
碼:
MainWindow.xaml :
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ClockWatcher" xmlns:System="clr-namespace:System;assembly=mscorlib"
x:Name="clockWatcherWindow"
x:Class="ClockWatcher.MainWindow"
Title="Clock Watcher" Height="554" Width="949"
KeyDown="KeysDown" Focusable="True" Closing="SaveSession"
DataContext="{Binding SM, RelativeSource={RelativeSource Self}}">
<TextBlock x:Name="programStartBlock" Text="{Binding StartTime, BindsDirectlyToSource=True, FallbackValue=Binding sucks so much!!!, StringFormat=ProgramStarted: \{0\}, TargetNullValue=This thing is null}" Padding="{DynamicResource labelPadding}" FontSize="{DynamicResource fontSize}"/>
<TextBlock x:Name="totalTimeLabel" Text="{Binding SM.currentSession.TotalTime, StringFormat=Total Time: \{0\}}" Padding="{DynamicResource labelPadding}" FontSize="{DynamicResource fontSize}"/>
</Window>
MainWindow.xaml.cs :
public partial class MainWindow : Window
{
private const string SESSION_FILENAME = "SessionFiles.xml";
/// <summary>
/// Represents, during selection mode, which TimeEntry is currently selected.
/// </summary>
public SessionManager SM { get; private set; }
public MainWindow()
{
InitializeComponent();
SM = new SessionManager();
SM.newAddedCommentEvent += currentTimeEntry_newComment;
SM.timeEntryDeletedEvent += currentTimeEntry_delete;
SM.commentEntryDeletedEvent += entry_delete;
}
}
SessionManager.cs :
public class SessionManager : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
[NonSerialized]
private DateTime _dtStartTime;
private Session current_session;
#region Properties
public DateTime StartTime
{
get
{
return _dtStartTime;
}
private set
{
if (_dtStartTime != value)
{
_dtStartTime = value;
OnPropertyChanged("StartTime");
}
}
}
public Session CurrentSession
{
get
{
return current_session;
}
set
{
if (current_session != value)
{
OnPropertyChanged("CurrentSession");
current_session = value;
}
}
}
#endregion
public SessionManager()
{
_dtStartTime = DateTime.Now;
}
private void OnPropertyChanged([CallerMemberName] string member_name = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(member_name));
}
}
}
Session.cs :
public class Session : INotifyPropertyChanged
{
private TimeSpan total_time;
public DateTime creationDate { get; private set; }
public event PropertyChangedEventHandler PropertyChanged;
public TimeSpan TotalTime
{
get
{
return total_time;
}
set
{
if (total_time != value)
{
OnPropertyChanged("TotalTime");
total_time = value;
}
}
}
public Session()
{
creationDate = DateTime.Now;
}
private void OnPropertyChanged([CallerMemberName] string member_name = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(member_name));
}
}
}
在第一個TextBlock中,僅寫入StartTime,而不是SM.StartTime。
從第一個TB中刪除ElementName。
將CurrentSession設為公共屬性,您的currentSession現在是私有的。
在您的SessionManager ctor中, current_session = new Session();
從XAML中刪除DataContext,使用this.DataContext = SM;
在您的窗口構造器中。
如果要在XAML中使用DataContext,
<Window.DataContext> <local:SessionManager /> </Window.DataContext>
標有正確答案的絕對是執行此操作的更好方法,但我只是想回答更多詳細信息,以解釋您發布的內容為何無效的原因。
問題是,當您在MainWindow.xaml中編寫DataContext={Binding SM, RelativeSource={RelativeSource Self}
時,在行SM = new SessionManager();
之前對綁定進行了評估SM = new SessionManager();
是在MainWindow.xaml.cs構造函數中執行的。
如果將SM的獲取程序更改為:
public SessionManager SM
{
get { return new SessionManager();}
}
這基本上可以確保WPF在評估您的綁定時,將為您的SM屬性獲得一個實際對象,而不是null。
只是認為這可能有助於下次理解並減少挫敗感:)。 問問題的方式,從技術上講,您需要在MainWindow類上實現INotifyPropertyChanged,這是一個很大的禁忌。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.