使用INotifyPropertyChanged进行绑定仍然无法正常工作

时间:2015-12-15 03:53:57

标签: c# wpf xaml binding

尝试了很多东西,仍然无法正常工作。绑定在两个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));
            }
        }
    }

2 个答案:

答案 0 :(得分:2)

  1. 在第一个TextBlock中,而不是SM.StartTime,只写入StartTime。

  2. 从第一个TB中删除ElementName。

  3. 创建CurrentSession公共属性,您的currentSession现在是私有的。

  4. 在SessionManager ctor中,current_session = new Session();

  5. 从XAML中删除DataContext,在窗口构造函数中使用this.DataContext = SM;

  6. 如果要在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,这是一个很大的禁忌。