0

Tried a lot of stuff, still doesn't work. Binding on the two TextBlocks don't work. Used INotifyPropertyChanged interface much like this code to no avail.

Code:

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)); } } } 
12
  • Please tell us what does not work and what do you want to achieve so we can help you better Commented Dec 15, 2015 at 3:56
  • You should provide more detail when you write a question on here. It will help you logically think about your problem, plus it will help users to answer your question. Commented Dec 15, 2015 at 3:57
  • Is "SM" defined in your MainWindow.xaml.cs? Can you post the code of the file that defines "SM"? Also, where did you implement INotifyPropertyChanged? Please post the code for that file as well, if it's not the MainWindow.xaml.cs Commented Dec 15, 2015 at 4:01
  • @DanielHakimi: try now. Commented Dec 15, 2015 at 4:13
  • @ParkSoonWai: try now. Commented Dec 15, 2015 at 4:13

2 Answers 2

2
  1. In first TextBlock, instead of SM.StartTime, write only StartTime.

  2. Remove ElementName from first TB.

  3. Make CurrentSession public property, Your currentSession is private now.

  4. In your SessionManager ctor, current_session = new Session();

  5. Remove DataContext from XAML, use this.DataContext = SM; in your window contructor.

  6. If you want to use DataContext in XAML,

    <Window.DataContext> <local:SessionManager /> </Window.DataContext> 
Sign up to request clarification or add additional context in comments.

7 Comments

1. Had that originally; did nothing. 2 Had that originally; did nothing. 3 Already have that; still nothing. I also explained this to Jamaxack in previous comments. 4 Had that originally; did nothing.
I have made application exactly as your code. Your edited code doesn't reflect suggested changes.
What I mean is I tried all that before I posted this, and those didn't work. However, upon further trial, I have found that setting the DataContext in the code-behind does work. You beat me back here on your next comment. However, it does not work for the currentsession.TotalTime. But I have to say: if that DataContext="" binding doesn't work in XAML code, then why is it in here in the first place? I have also tried this before numerous times, and one time for a grade where I did almost exactly this, and I was able to set the data context in XAML code, and it worked. Today it refuses to do so.
@SageKelly Check updated answer now. Also check your code for common silly mistakes.
Well thank you for the "common silly mistakes" thing. That, indeed, WAS the last error. Forgot to capitalize currentsession in the binding instruction. Thanks for your patience and the help you've given me.
|
0

The marked correct answer is definitely the better way to do it, but I just wanted to answer explaining more in detail why what you posted didn't work.

The issue is that when you wrote DataContext={Binding SM, RelativeSource={RelativeSource Self} in your MainWindow.xaml, the binding was evaluted before your line SM = new SessionManager(); was executed in your MainWindow.xaml.cs constructor.

You can see this in effect if you changed your getter for SM to:

public SessionManager SM { get { return new SessionManager();} } 

This basically ensures that when WPF evaluates your binding, it'll get an actual object for your SM property instead of null.

Just thought perhaps this will help understanding and reduce frustration next time :). The way you asked your question, you technically needed to implement INotifyPropertyChanged on your MainWindow class, which is a big no-no.

3 Comments

So I'm new to this WPF development. I have two questions. 1) Is it possible that would have worked if I had just moved SM=new SessionManager() after the InitalizeComponent() method call? 2) Why is it a big no-no to implement INotifyPropertyChanged on the MainWindow, so I don't try it on another project?
1) It seems you already have it this way? Did you mean move the new SessionManager() call to BEFORE InitializeComponent()? If so, yes it will work because the xaml is loaded within InitializeComponent(). I just tested on my machine and verified. 2) Because with WPF, most people do some sort of MVVM design in order to separate the view (xaml + xaml.cs) from the data (viewmodel). INotifyPropertyChanged (INPC) is basically nearly always implemented by the ViewModel class. If you implement INPC in your view class, it implies that you're mixing your data with your view, which is the actual no-no :)
Oh and before someone jumps on my comment, some implementers of MVVM (Model View ViewModel) will argue that the implementation of INotifyPropertyChanged should be on the model; the are valid arguments for both ways. Check out stackoverflow.com/questions/772214/…

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.