尝试了很多东西,仍然无法正常工作。绑定在两个TextBlocks上不起作用。与this code非常相似的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));
}
}
}
答案 0 :(得分:2)
在第一个TextBlock中,而不是SM.StartTime,只写入StartTime。
从第一个TB中删除ElementName。
创建CurrentSession公共属性,您的currentSession现在是私有的。
在SessionManager ctor中,current_session = new Session();
从XAML中删除DataContext,在窗口构造函数中使用this.DataContext = SM;
。
如果要在XAML中使用DataContext,
<Window.DataContext>
<local:SessionManager />
</Window.DataContext>
答案 1 :(得分:0)
标记正确的答案肯定是更好的方法,但我只是想回答详细解释为什么你发布的内容不起作用。
问题在于,当您在MainWindow.xaml中编写class BritishPerson
{
public String name = "A british name";
public void salute()
{
System.out.println("Good Morning!");
}
}
class ScottishPerson extends BritishPerson
{
public String name = "A scottish name "; //Variable overriding
public String clanName = "MacDonald";
public ScottishPerson() {
// TODO Auto-generated constructor stub
}
public ScottishPerson(String name) {
super.name = name;
this.name = name;
}
@Override
public void salute() //Method overriding
{
System.out.println("Madainn Mhath!");
}
public void warcry()
{
System.out.println("Alba Gu Brath!");
}
}
public class Driver {
public static void main(String[] args) {
// TODO Auto-generated method stub
ScottishPerson scottishPerson = new ScottishPerson(); //Created as a subclass, can always be upcasted.
BritishPerson britishPerson = new BritishPerson(); //Created as the superclass, throws an error when downcasted.
BritishPerson britishPersonUpcasted = new ScottishPerson("Another scottish name"); //Created as the subclass but automatically upcasted, can be downcasted again.
//Checking the methods and parameters of scottishPerson
scottishPerson.salute();
scottishPerson.warcry();
System.out.println(scottishPerson.name);
System.out.println(scottishPerson.clanName);
//Checking the methods and parameters of britishPerson
britishPerson.salute();
System.out.println(britishPerson.name);
//Checking the methods and parameters of britishPersonUpcasted
britishPersonUpcasted.salute();
System.out.println(britishPersonUpcasted.name);
}
}
时,会在您的MainWindow.xaml.cs构造函数中执行行DataContext={Binding SM, RelativeSource={RelativeSource Self}
之前评估绑定。
如果您将SM的getter更改为:
,则可以看到此效果SM = new SessionManager();
这基本上确保了当WPF评估你的绑定时,它将获得SM属性的实际对象而不是null。
想到也许这将有助于理解并减少下次的挫折:)。你提出问题的方式,你在技术上需要在MainWindow类上实现INotifyPropertyChanged,这是一个很大的禁忌。