Why does not display the content of the label?
So I have got a view with a label and I have got a ViewModel for it.
ViewModelBase
public abstract class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected virtual bool SetAndRaisePropertyChanged<T>(ref T storage, T value, [CallerMemberName] string propertyName = "")
{
if (EqualityComparer<T>.Default.Equals(storage, value))
return false;
storage = value;
this.RaisePropertyChanged(propertyName);
return true;
}
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
This is how the ViewModel looks like:
private string _balance = "1111$";
public string Balance
{
get { return _balance; }
set { SetAndRaisePropertyChanged(ref _balance, value); }
}
And here is the view:
<UserControl x:Class="monei_project.MainUpperView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:project"
xmlns:vm="clr-namespace:project.ViewModels"
mc:Ignorable="d"
d:DesignHeight="100" d:DesignWidth="2200" FontFamily="Open Sans">
<UserControl.Resources>
<vm:MainUpperViewModel x:Key="MainUpperViewModel"/>
</UserControl.Resources>
<Grid DataContext="{Binding Source={StaticResource MainUpperViewModel}}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<Rectangle Grid.RowSpan="1" Grid.ColumnSpan="22" Fill="#013542"></Rectangle>
<Label Grid.Column="6" Grid.ColumnSpan="2" VerticalAlignment="Center" Foreground="White" FontSize="16">Balance:</Label>
<Label x:Name="lblBalance" Grid.Column="7" Grid.ColumnSpan="5" VerticalAlignment="Center" Foreground="White" FontFamily="Open Sans SemiBold" FontSize="24" Margin="55,28,45,33">
<Label.Content>
<Binding Path="Balance"/>
</Label.Content>
</Label>
</Grid>
In the designer, I can see the content of the label
But when I run the application, the label is empty
What is the problem?
I have already created some ViewModel, but there I worked with textboxes. We used INotifyPropertyChanged interface, and I am not sure how does it work, so my guess was, that it sets the content, but won't display it, because the label is not updating, so I tried to use the OnPropertyChanged function with a PropertyChangedEventHandler, what we used earlier to the other ViewModels, but it didn't work either, I do not know what can be wrong.
c# xaml mvvm label
add a comment |
So I have got a view with a label and I have got a ViewModel for it.
ViewModelBase
public abstract class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected virtual bool SetAndRaisePropertyChanged<T>(ref T storage, T value, [CallerMemberName] string propertyName = "")
{
if (EqualityComparer<T>.Default.Equals(storage, value))
return false;
storage = value;
this.RaisePropertyChanged(propertyName);
return true;
}
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
This is how the ViewModel looks like:
private string _balance = "1111$";
public string Balance
{
get { return _balance; }
set { SetAndRaisePropertyChanged(ref _balance, value); }
}
And here is the view:
<UserControl x:Class="monei_project.MainUpperView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:project"
xmlns:vm="clr-namespace:project.ViewModels"
mc:Ignorable="d"
d:DesignHeight="100" d:DesignWidth="2200" FontFamily="Open Sans">
<UserControl.Resources>
<vm:MainUpperViewModel x:Key="MainUpperViewModel"/>
</UserControl.Resources>
<Grid DataContext="{Binding Source={StaticResource MainUpperViewModel}}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<Rectangle Grid.RowSpan="1" Grid.ColumnSpan="22" Fill="#013542"></Rectangle>
<Label Grid.Column="6" Grid.ColumnSpan="2" VerticalAlignment="Center" Foreground="White" FontSize="16">Balance:</Label>
<Label x:Name="lblBalance" Grid.Column="7" Grid.ColumnSpan="5" VerticalAlignment="Center" Foreground="White" FontFamily="Open Sans SemiBold" FontSize="24" Margin="55,28,45,33">
<Label.Content>
<Binding Path="Balance"/>
</Label.Content>
</Label>
</Grid>
In the designer, I can see the content of the label
But when I run the application, the label is empty
What is the problem?
I have already created some ViewModel, but there I worked with textboxes. We used INotifyPropertyChanged interface, and I am not sure how does it work, so my guess was, that it sets the content, but won't display it, because the label is not updating, so I tried to use the OnPropertyChanged function with a PropertyChangedEventHandler, what we used earlier to the other ViewModels, but it didn't work either, I do not know what can be wrong.
c# xaml mvvm label
1
you understood well the issue and you were on the right path, see my answer for more ^^
– Mikitori
Nov 15 '18 at 17:00
add a comment |
So I have got a view with a label and I have got a ViewModel for it.
ViewModelBase
public abstract class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected virtual bool SetAndRaisePropertyChanged<T>(ref T storage, T value, [CallerMemberName] string propertyName = "")
{
if (EqualityComparer<T>.Default.Equals(storage, value))
return false;
storage = value;
this.RaisePropertyChanged(propertyName);
return true;
}
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
This is how the ViewModel looks like:
private string _balance = "1111$";
public string Balance
{
get { return _balance; }
set { SetAndRaisePropertyChanged(ref _balance, value); }
}
And here is the view:
<UserControl x:Class="monei_project.MainUpperView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:project"
xmlns:vm="clr-namespace:project.ViewModels"
mc:Ignorable="d"
d:DesignHeight="100" d:DesignWidth="2200" FontFamily="Open Sans">
<UserControl.Resources>
<vm:MainUpperViewModel x:Key="MainUpperViewModel"/>
</UserControl.Resources>
<Grid DataContext="{Binding Source={StaticResource MainUpperViewModel}}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<Rectangle Grid.RowSpan="1" Grid.ColumnSpan="22" Fill="#013542"></Rectangle>
<Label Grid.Column="6" Grid.ColumnSpan="2" VerticalAlignment="Center" Foreground="White" FontSize="16">Balance:</Label>
<Label x:Name="lblBalance" Grid.Column="7" Grid.ColumnSpan="5" VerticalAlignment="Center" Foreground="White" FontFamily="Open Sans SemiBold" FontSize="24" Margin="55,28,45,33">
<Label.Content>
<Binding Path="Balance"/>
</Label.Content>
</Label>
</Grid>
In the designer, I can see the content of the label
But when I run the application, the label is empty
What is the problem?
I have already created some ViewModel, but there I worked with textboxes. We used INotifyPropertyChanged interface, and I am not sure how does it work, so my guess was, that it sets the content, but won't display it, because the label is not updating, so I tried to use the OnPropertyChanged function with a PropertyChangedEventHandler, what we used earlier to the other ViewModels, but it didn't work either, I do not know what can be wrong.
c# xaml mvvm label
So I have got a view with a label and I have got a ViewModel for it.
ViewModelBase
public abstract class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected virtual bool SetAndRaisePropertyChanged<T>(ref T storage, T value, [CallerMemberName] string propertyName = "")
{
if (EqualityComparer<T>.Default.Equals(storage, value))
return false;
storage = value;
this.RaisePropertyChanged(propertyName);
return true;
}
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
This is how the ViewModel looks like:
private string _balance = "1111$";
public string Balance
{
get { return _balance; }
set { SetAndRaisePropertyChanged(ref _balance, value); }
}
And here is the view:
<UserControl x:Class="monei_project.MainUpperView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:project"
xmlns:vm="clr-namespace:project.ViewModels"
mc:Ignorable="d"
d:DesignHeight="100" d:DesignWidth="2200" FontFamily="Open Sans">
<UserControl.Resources>
<vm:MainUpperViewModel x:Key="MainUpperViewModel"/>
</UserControl.Resources>
<Grid DataContext="{Binding Source={StaticResource MainUpperViewModel}}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<Rectangle Grid.RowSpan="1" Grid.ColumnSpan="22" Fill="#013542"></Rectangle>
<Label Grid.Column="6" Grid.ColumnSpan="2" VerticalAlignment="Center" Foreground="White" FontSize="16">Balance:</Label>
<Label x:Name="lblBalance" Grid.Column="7" Grid.ColumnSpan="5" VerticalAlignment="Center" Foreground="White" FontFamily="Open Sans SemiBold" FontSize="24" Margin="55,28,45,33">
<Label.Content>
<Binding Path="Balance"/>
</Label.Content>
</Label>
</Grid>
In the designer, I can see the content of the label
But when I run the application, the label is empty
What is the problem?
I have already created some ViewModel, but there I worked with textboxes. We used INotifyPropertyChanged interface, and I am not sure how does it work, so my guess was, that it sets the content, but won't display it, because the label is not updating, so I tried to use the OnPropertyChanged function with a PropertyChangedEventHandler, what we used earlier to the other ViewModels, but it didn't work either, I do not know what can be wrong.
c# xaml mvvm label
c# xaml mvvm label
edited Nov 16 '18 at 12:55
AME
asked Nov 15 '18 at 16:51
AMEAME
555
555
1
you understood well the issue and you were on the right path, see my answer for more ^^
– Mikitori
Nov 15 '18 at 17:00
add a comment |
1
you understood well the issue and you were on the right path, see my answer for more ^^
– Mikitori
Nov 15 '18 at 17:00
1
1
you understood well the issue and you were on the right path, see my answer for more ^^
– Mikitori
Nov 15 '18 at 17:00
you understood well the issue and you were on the right path, see my answer for more ^^
– Mikitori
Nov 15 '18 at 17:00
add a comment |
3 Answers
3
active
oldest
votes
There are some frameworks providing class already implementing the needed interfaces, if you want to do it yourself, here is a possibility:
First you have your ViewModelBase and all your ViewModels should inherit it
public abstract class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected virtual bool SetAndRaisePropertyChanged<T>(ref T storage, T value, [CallerMemberName] string propertyName = "")
{
if (EqualityComparer<T>.Default.Equals(storage, value))
return false;
storage = value;
this.RaisePropertyChanged(propertyName);
return true;
}
}
then in your viewmodel you will declare your property like this:
private String _mBalance;
public String Balance
{
get { return _mBalance; }
set => SetAndRaisePropertyChanged(ref _mBalance, value);
}
[EDIT]: I want to keep the history of the answer, so check my edit below with full fonctionnal example:
Usually I split in more files, but i wanted to stay simple, so you need 2 files (I'm trying to apply MVVM pattern so i'm adding directories):
- ViewsMainWindow.xaml
- ViewModelsMainWindowViewModel.cs
ViewsMainWindow.xaml:
<Window x:Class="StackOverflow_DBG.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:StackOverflow_DBG"
xmlns:viewmodels="clr-namespace:StackOverflow_DBG.ViewModels"
mc:Ignorable="d"
Title="MainWindow" Height="100" Width="400">
<Window.DataContext>
<viewmodels:MainWindowViewModel/>
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Grid.Row="1" Grid.Column="0" Content="{Binding LabelTxt}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding ValueTxt}"/>
<Button Grid.Row="1" Grid.Column="2" Content="Change Label" Command="{Binding ChangeLabel}"/>
</Grid>
</Window>
ViewModelsMainWindowViewModel.cs:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace StackOverflow_DBG.ViewModels
{
public abstract class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected virtual bool SetAndRaisePropertyChanged<T>(ref T storage, T value, [CallerMemberName] string propertyName = "")
{
if (EqualityComparer<T>.Default.Equals(storage, value))
return false;
storage = value;
this.RaisePropertyChanged(propertyName);
return true;
}
}
public class RelayCommand : ICommand
{
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
private Action methodToExecute;
private Func<bool> canExecuteEvaluator;
public RelayCommand(Action methodToExecute, Func<bool> canExecuteEvaluator)
{
this.methodToExecute = methodToExecute;
this.canExecuteEvaluator = canExecuteEvaluator;
}
public RelayCommand(Action methodToExecute)
: this(methodToExecute, null)
{
}
public bool CanExecute(object parameter)
{
if (this.canExecuteEvaluator == null)
{
return true;
}
else
{
bool result = this.canExecuteEvaluator.Invoke();
return result;
}
}
public void Execute(object parameter)
{
this.methodToExecute.Invoke();
}
}
class MainWindowViewModel : ViewModelBase
{
private String m_LabelTxt = "Foo";
public String LabelTxt
{
get { return m_LabelTxt; }
set => SetAndRaisePropertyChanged(ref m_LabelTxt, value);
}
private String m_ValueTxt;
public String ValueTxt
{
get { return m_ValueTxt; }
set => SetAndRaisePropertyChanged(ref m_ValueTxt, value);
}
private RelayCommand m_ChangeLabel;
public RelayCommand ChangeLabel
{
get { return m_ChangeLabel; }
set { m_ChangeLabel = value; }
}
public MainWindowViewModel()
{
ChangeLabel = new RelayCommand(() => {
if (LabelTxt == "Foo")
{
LabelTxt = "Bar ";
}
else
{
LabelTxt = "Foo ";
}
});
}
}
}
This way you also see how to bind button for example. Press the button to see that the update is well done.
If using same directories than me, remember to edit app.xaml to use StartupUri="Views/MainWindow.xaml">
instead of
StartupUri="MainWindow.xaml">
Thank you for your answer. This ViewModelBase was a really great idea, I just start to think in this way, when I am programming. So I created that BaseViewModel what you suggested with three function. I used three function because I really do not understand how are these works. I have got two function from your example, and I also add the function what we used earlier in this project. I will edit the post, you can see there. What are the functions doing? Still not working. Which function should I bind to which XAML property to get it work?
– AME
Nov 15 '18 at 17:22
2 issues, you shouldn't need the OnPropertyChanged, it's already handled by the code I provided. The really big issue in your modification is : set { SetAndRaisePropertyChanged(ref _balance, "1111$"); } you really need to keep the code I posted. the word value is a key word and means the value you provided to set yourt property. take my code and then you can set your property like a classical variable: Balance = "1111$"; if you want to initialize with a default value, you do it on the private part: private String _mBalance = String.Empty; for example
– Mikitori
Nov 15 '18 at 21:04
For the datacontext (you are setting it in the xaml) your way may work but I think you can do it better. Maybe tomorrow i can share more code if needed but try what I said, it should be ok.
– Mikitori
Nov 15 '18 at 21:07
Still not figured it out, how to get it work, so i would appreciate it.
– AME
Nov 16 '18 at 8:11
Full example added ;)
– Mikitori
Nov 16 '18 at 10:24
|
show 3 more comments
Have you properly set the DataContext on the window/control to your view model? You need to set your DataContext before you are able to use bindings. And as such, you should probably use the proper way for binding:
<Label Content="{Binding Balance}" ... />
Edit:
Okay, I'll give you a concrete example of what I mean. Also, you're going to run into a lot of issues using a view model as a StaticResource
. Why do I say this? Because once you start adding dependencies to your view model (accessing business logic, etc), you will need some form of dependency injection (DI) or a similar way to do so.
So you have your ViewModelBase
, so I'll use that and not duplicate myself. Here's a simple view model:
public class AccountViewModel : ViewModelBase
{
string _balance = "1111$";
public AccountViewModel(string accountNumber)
{
AccountNumber = accountNumber;
}
public string AccountNumber { get; }
public string Balance
{
get { return _balance; }
set { SetAndRaisePropertyChanged(ref _balance, value); }
}
}
Here's the view code (MainWindow.xaml
):
<Window x:Class="testProj.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008">
<Grid>
<Label Content="{Binding Balance}" />
</Grid>
</Window>
And the code behind (MainWindow.xaml.cs
):
public partial class MainWindow
{
public MainWindow(AccountViewModel dataContext)
{
DataContext = dataContext;
InitializeComponent();
}
}
And for fun, the App.xaml.cs
(set up for BuildAction - Page):
public partial class App
{
[STAThread]
public static void Main(string args)
{
new MainWindow(new AccountViewModel("123456789")).ShowDialog();
}
}
This will show you what you are expecting, and display the Balance correctly. There are a few things you can try to see what your issue is:
- Is there any information in the output window when debugging that tells you if a binding error is occurring?
Can you give a shorter version of your application showing all parts (i.e. a short project that duplicates the issue) and upload it somewhere?
I do not know what do you mean by DataContext, but I updated the the XAML code and you can see there how did I bind the ViewModel to the View.
– AME
Nov 15 '18 at 18:37
Anyway I tried your code, and still not working, In my opinion it is doing the same.
– AME
Nov 15 '18 at 18:40
Maybe I was not clear. So the binding is works fine when I update the view, but when I first open the window, it won't display the initial value of the property, just after I trigger it with an update
– AME
Nov 17 '18 at 14:08
Have you tried using the Live Visual Tree explorer in Visual Studio to inspect the label and see what itsContent
property is initially? What debugging steps have you taken to validate that the Balance property is initialized properly to have the value you've expected?
– RecursiveNerd
Nov 19 '18 at 20:01
The margin was the problem. :)
– AME
Nov 20 '18 at 18:19
add a comment |
Delete the margin solved the problem. I guess the margin pushed out the label.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53324293%2fwhy-does-not-display-the-content-of-the-label%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
There are some frameworks providing class already implementing the needed interfaces, if you want to do it yourself, here is a possibility:
First you have your ViewModelBase and all your ViewModels should inherit it
public abstract class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected virtual bool SetAndRaisePropertyChanged<T>(ref T storage, T value, [CallerMemberName] string propertyName = "")
{
if (EqualityComparer<T>.Default.Equals(storage, value))
return false;
storage = value;
this.RaisePropertyChanged(propertyName);
return true;
}
}
then in your viewmodel you will declare your property like this:
private String _mBalance;
public String Balance
{
get { return _mBalance; }
set => SetAndRaisePropertyChanged(ref _mBalance, value);
}
[EDIT]: I want to keep the history of the answer, so check my edit below with full fonctionnal example:
Usually I split in more files, but i wanted to stay simple, so you need 2 files (I'm trying to apply MVVM pattern so i'm adding directories):
- ViewsMainWindow.xaml
- ViewModelsMainWindowViewModel.cs
ViewsMainWindow.xaml:
<Window x:Class="StackOverflow_DBG.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:StackOverflow_DBG"
xmlns:viewmodels="clr-namespace:StackOverflow_DBG.ViewModels"
mc:Ignorable="d"
Title="MainWindow" Height="100" Width="400">
<Window.DataContext>
<viewmodels:MainWindowViewModel/>
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Grid.Row="1" Grid.Column="0" Content="{Binding LabelTxt}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding ValueTxt}"/>
<Button Grid.Row="1" Grid.Column="2" Content="Change Label" Command="{Binding ChangeLabel}"/>
</Grid>
</Window>
ViewModelsMainWindowViewModel.cs:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace StackOverflow_DBG.ViewModels
{
public abstract class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected virtual bool SetAndRaisePropertyChanged<T>(ref T storage, T value, [CallerMemberName] string propertyName = "")
{
if (EqualityComparer<T>.Default.Equals(storage, value))
return false;
storage = value;
this.RaisePropertyChanged(propertyName);
return true;
}
}
public class RelayCommand : ICommand
{
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
private Action methodToExecute;
private Func<bool> canExecuteEvaluator;
public RelayCommand(Action methodToExecute, Func<bool> canExecuteEvaluator)
{
this.methodToExecute = methodToExecute;
this.canExecuteEvaluator = canExecuteEvaluator;
}
public RelayCommand(Action methodToExecute)
: this(methodToExecute, null)
{
}
public bool CanExecute(object parameter)
{
if (this.canExecuteEvaluator == null)
{
return true;
}
else
{
bool result = this.canExecuteEvaluator.Invoke();
return result;
}
}
public void Execute(object parameter)
{
this.methodToExecute.Invoke();
}
}
class MainWindowViewModel : ViewModelBase
{
private String m_LabelTxt = "Foo";
public String LabelTxt
{
get { return m_LabelTxt; }
set => SetAndRaisePropertyChanged(ref m_LabelTxt, value);
}
private String m_ValueTxt;
public String ValueTxt
{
get { return m_ValueTxt; }
set => SetAndRaisePropertyChanged(ref m_ValueTxt, value);
}
private RelayCommand m_ChangeLabel;
public RelayCommand ChangeLabel
{
get { return m_ChangeLabel; }
set { m_ChangeLabel = value; }
}
public MainWindowViewModel()
{
ChangeLabel = new RelayCommand(() => {
if (LabelTxt == "Foo")
{
LabelTxt = "Bar ";
}
else
{
LabelTxt = "Foo ";
}
});
}
}
}
This way you also see how to bind button for example. Press the button to see that the update is well done.
If using same directories than me, remember to edit app.xaml to use StartupUri="Views/MainWindow.xaml">
instead of
StartupUri="MainWindow.xaml">
Thank you for your answer. This ViewModelBase was a really great idea, I just start to think in this way, when I am programming. So I created that BaseViewModel what you suggested with three function. I used three function because I really do not understand how are these works. I have got two function from your example, and I also add the function what we used earlier in this project. I will edit the post, you can see there. What are the functions doing? Still not working. Which function should I bind to which XAML property to get it work?
– AME
Nov 15 '18 at 17:22
2 issues, you shouldn't need the OnPropertyChanged, it's already handled by the code I provided. The really big issue in your modification is : set { SetAndRaisePropertyChanged(ref _balance, "1111$"); } you really need to keep the code I posted. the word value is a key word and means the value you provided to set yourt property. take my code and then you can set your property like a classical variable: Balance = "1111$"; if you want to initialize with a default value, you do it on the private part: private String _mBalance = String.Empty; for example
– Mikitori
Nov 15 '18 at 21:04
For the datacontext (you are setting it in the xaml) your way may work but I think you can do it better. Maybe tomorrow i can share more code if needed but try what I said, it should be ok.
– Mikitori
Nov 15 '18 at 21:07
Still not figured it out, how to get it work, so i would appreciate it.
– AME
Nov 16 '18 at 8:11
Full example added ;)
– Mikitori
Nov 16 '18 at 10:24
|
show 3 more comments
There are some frameworks providing class already implementing the needed interfaces, if you want to do it yourself, here is a possibility:
First you have your ViewModelBase and all your ViewModels should inherit it
public abstract class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected virtual bool SetAndRaisePropertyChanged<T>(ref T storage, T value, [CallerMemberName] string propertyName = "")
{
if (EqualityComparer<T>.Default.Equals(storage, value))
return false;
storage = value;
this.RaisePropertyChanged(propertyName);
return true;
}
}
then in your viewmodel you will declare your property like this:
private String _mBalance;
public String Balance
{
get { return _mBalance; }
set => SetAndRaisePropertyChanged(ref _mBalance, value);
}
[EDIT]: I want to keep the history of the answer, so check my edit below with full fonctionnal example:
Usually I split in more files, but i wanted to stay simple, so you need 2 files (I'm trying to apply MVVM pattern so i'm adding directories):
- ViewsMainWindow.xaml
- ViewModelsMainWindowViewModel.cs
ViewsMainWindow.xaml:
<Window x:Class="StackOverflow_DBG.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:StackOverflow_DBG"
xmlns:viewmodels="clr-namespace:StackOverflow_DBG.ViewModels"
mc:Ignorable="d"
Title="MainWindow" Height="100" Width="400">
<Window.DataContext>
<viewmodels:MainWindowViewModel/>
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Grid.Row="1" Grid.Column="0" Content="{Binding LabelTxt}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding ValueTxt}"/>
<Button Grid.Row="1" Grid.Column="2" Content="Change Label" Command="{Binding ChangeLabel}"/>
</Grid>
</Window>
ViewModelsMainWindowViewModel.cs:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace StackOverflow_DBG.ViewModels
{
public abstract class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected virtual bool SetAndRaisePropertyChanged<T>(ref T storage, T value, [CallerMemberName] string propertyName = "")
{
if (EqualityComparer<T>.Default.Equals(storage, value))
return false;
storage = value;
this.RaisePropertyChanged(propertyName);
return true;
}
}
public class RelayCommand : ICommand
{
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
private Action methodToExecute;
private Func<bool> canExecuteEvaluator;
public RelayCommand(Action methodToExecute, Func<bool> canExecuteEvaluator)
{
this.methodToExecute = methodToExecute;
this.canExecuteEvaluator = canExecuteEvaluator;
}
public RelayCommand(Action methodToExecute)
: this(methodToExecute, null)
{
}
public bool CanExecute(object parameter)
{
if (this.canExecuteEvaluator == null)
{
return true;
}
else
{
bool result = this.canExecuteEvaluator.Invoke();
return result;
}
}
public void Execute(object parameter)
{
this.methodToExecute.Invoke();
}
}
class MainWindowViewModel : ViewModelBase
{
private String m_LabelTxt = "Foo";
public String LabelTxt
{
get { return m_LabelTxt; }
set => SetAndRaisePropertyChanged(ref m_LabelTxt, value);
}
private String m_ValueTxt;
public String ValueTxt
{
get { return m_ValueTxt; }
set => SetAndRaisePropertyChanged(ref m_ValueTxt, value);
}
private RelayCommand m_ChangeLabel;
public RelayCommand ChangeLabel
{
get { return m_ChangeLabel; }
set { m_ChangeLabel = value; }
}
public MainWindowViewModel()
{
ChangeLabel = new RelayCommand(() => {
if (LabelTxt == "Foo")
{
LabelTxt = "Bar ";
}
else
{
LabelTxt = "Foo ";
}
});
}
}
}
This way you also see how to bind button for example. Press the button to see that the update is well done.
If using same directories than me, remember to edit app.xaml to use StartupUri="Views/MainWindow.xaml">
instead of
StartupUri="MainWindow.xaml">
Thank you for your answer. This ViewModelBase was a really great idea, I just start to think in this way, when I am programming. So I created that BaseViewModel what you suggested with three function. I used three function because I really do not understand how are these works. I have got two function from your example, and I also add the function what we used earlier in this project. I will edit the post, you can see there. What are the functions doing? Still not working. Which function should I bind to which XAML property to get it work?
– AME
Nov 15 '18 at 17:22
2 issues, you shouldn't need the OnPropertyChanged, it's already handled by the code I provided. The really big issue in your modification is : set { SetAndRaisePropertyChanged(ref _balance, "1111$"); } you really need to keep the code I posted. the word value is a key word and means the value you provided to set yourt property. take my code and then you can set your property like a classical variable: Balance = "1111$"; if you want to initialize with a default value, you do it on the private part: private String _mBalance = String.Empty; for example
– Mikitori
Nov 15 '18 at 21:04
For the datacontext (you are setting it in the xaml) your way may work but I think you can do it better. Maybe tomorrow i can share more code if needed but try what I said, it should be ok.
– Mikitori
Nov 15 '18 at 21:07
Still not figured it out, how to get it work, so i would appreciate it.
– AME
Nov 16 '18 at 8:11
Full example added ;)
– Mikitori
Nov 16 '18 at 10:24
|
show 3 more comments
There are some frameworks providing class already implementing the needed interfaces, if you want to do it yourself, here is a possibility:
First you have your ViewModelBase and all your ViewModels should inherit it
public abstract class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected virtual bool SetAndRaisePropertyChanged<T>(ref T storage, T value, [CallerMemberName] string propertyName = "")
{
if (EqualityComparer<T>.Default.Equals(storage, value))
return false;
storage = value;
this.RaisePropertyChanged(propertyName);
return true;
}
}
then in your viewmodel you will declare your property like this:
private String _mBalance;
public String Balance
{
get { return _mBalance; }
set => SetAndRaisePropertyChanged(ref _mBalance, value);
}
[EDIT]: I want to keep the history of the answer, so check my edit below with full fonctionnal example:
Usually I split in more files, but i wanted to stay simple, so you need 2 files (I'm trying to apply MVVM pattern so i'm adding directories):
- ViewsMainWindow.xaml
- ViewModelsMainWindowViewModel.cs
ViewsMainWindow.xaml:
<Window x:Class="StackOverflow_DBG.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:StackOverflow_DBG"
xmlns:viewmodels="clr-namespace:StackOverflow_DBG.ViewModels"
mc:Ignorable="d"
Title="MainWindow" Height="100" Width="400">
<Window.DataContext>
<viewmodels:MainWindowViewModel/>
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Grid.Row="1" Grid.Column="0" Content="{Binding LabelTxt}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding ValueTxt}"/>
<Button Grid.Row="1" Grid.Column="2" Content="Change Label" Command="{Binding ChangeLabel}"/>
</Grid>
</Window>
ViewModelsMainWindowViewModel.cs:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace StackOverflow_DBG.ViewModels
{
public abstract class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected virtual bool SetAndRaisePropertyChanged<T>(ref T storage, T value, [CallerMemberName] string propertyName = "")
{
if (EqualityComparer<T>.Default.Equals(storage, value))
return false;
storage = value;
this.RaisePropertyChanged(propertyName);
return true;
}
}
public class RelayCommand : ICommand
{
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
private Action methodToExecute;
private Func<bool> canExecuteEvaluator;
public RelayCommand(Action methodToExecute, Func<bool> canExecuteEvaluator)
{
this.methodToExecute = methodToExecute;
this.canExecuteEvaluator = canExecuteEvaluator;
}
public RelayCommand(Action methodToExecute)
: this(methodToExecute, null)
{
}
public bool CanExecute(object parameter)
{
if (this.canExecuteEvaluator == null)
{
return true;
}
else
{
bool result = this.canExecuteEvaluator.Invoke();
return result;
}
}
public void Execute(object parameter)
{
this.methodToExecute.Invoke();
}
}
class MainWindowViewModel : ViewModelBase
{
private String m_LabelTxt = "Foo";
public String LabelTxt
{
get { return m_LabelTxt; }
set => SetAndRaisePropertyChanged(ref m_LabelTxt, value);
}
private String m_ValueTxt;
public String ValueTxt
{
get { return m_ValueTxt; }
set => SetAndRaisePropertyChanged(ref m_ValueTxt, value);
}
private RelayCommand m_ChangeLabel;
public RelayCommand ChangeLabel
{
get { return m_ChangeLabel; }
set { m_ChangeLabel = value; }
}
public MainWindowViewModel()
{
ChangeLabel = new RelayCommand(() => {
if (LabelTxt == "Foo")
{
LabelTxt = "Bar ";
}
else
{
LabelTxt = "Foo ";
}
});
}
}
}
This way you also see how to bind button for example. Press the button to see that the update is well done.
If using same directories than me, remember to edit app.xaml to use StartupUri="Views/MainWindow.xaml">
instead of
StartupUri="MainWindow.xaml">
There are some frameworks providing class already implementing the needed interfaces, if you want to do it yourself, here is a possibility:
First you have your ViewModelBase and all your ViewModels should inherit it
public abstract class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected virtual bool SetAndRaisePropertyChanged<T>(ref T storage, T value, [CallerMemberName] string propertyName = "")
{
if (EqualityComparer<T>.Default.Equals(storage, value))
return false;
storage = value;
this.RaisePropertyChanged(propertyName);
return true;
}
}
then in your viewmodel you will declare your property like this:
private String _mBalance;
public String Balance
{
get { return _mBalance; }
set => SetAndRaisePropertyChanged(ref _mBalance, value);
}
[EDIT]: I want to keep the history of the answer, so check my edit below with full fonctionnal example:
Usually I split in more files, but i wanted to stay simple, so you need 2 files (I'm trying to apply MVVM pattern so i'm adding directories):
- ViewsMainWindow.xaml
- ViewModelsMainWindowViewModel.cs
ViewsMainWindow.xaml:
<Window x:Class="StackOverflow_DBG.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:StackOverflow_DBG"
xmlns:viewmodels="clr-namespace:StackOverflow_DBG.ViewModels"
mc:Ignorable="d"
Title="MainWindow" Height="100" Width="400">
<Window.DataContext>
<viewmodels:MainWindowViewModel/>
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Grid.Row="1" Grid.Column="0" Content="{Binding LabelTxt}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding ValueTxt}"/>
<Button Grid.Row="1" Grid.Column="2" Content="Change Label" Command="{Binding ChangeLabel}"/>
</Grid>
</Window>
ViewModelsMainWindowViewModel.cs:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace StackOverflow_DBG.ViewModels
{
public abstract class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected virtual bool SetAndRaisePropertyChanged<T>(ref T storage, T value, [CallerMemberName] string propertyName = "")
{
if (EqualityComparer<T>.Default.Equals(storage, value))
return false;
storage = value;
this.RaisePropertyChanged(propertyName);
return true;
}
}
public class RelayCommand : ICommand
{
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
private Action methodToExecute;
private Func<bool> canExecuteEvaluator;
public RelayCommand(Action methodToExecute, Func<bool> canExecuteEvaluator)
{
this.methodToExecute = methodToExecute;
this.canExecuteEvaluator = canExecuteEvaluator;
}
public RelayCommand(Action methodToExecute)
: this(methodToExecute, null)
{
}
public bool CanExecute(object parameter)
{
if (this.canExecuteEvaluator == null)
{
return true;
}
else
{
bool result = this.canExecuteEvaluator.Invoke();
return result;
}
}
public void Execute(object parameter)
{
this.methodToExecute.Invoke();
}
}
class MainWindowViewModel : ViewModelBase
{
private String m_LabelTxt = "Foo";
public String LabelTxt
{
get { return m_LabelTxt; }
set => SetAndRaisePropertyChanged(ref m_LabelTxt, value);
}
private String m_ValueTxt;
public String ValueTxt
{
get { return m_ValueTxt; }
set => SetAndRaisePropertyChanged(ref m_ValueTxt, value);
}
private RelayCommand m_ChangeLabel;
public RelayCommand ChangeLabel
{
get { return m_ChangeLabel; }
set { m_ChangeLabel = value; }
}
public MainWindowViewModel()
{
ChangeLabel = new RelayCommand(() => {
if (LabelTxt == "Foo")
{
LabelTxt = "Bar ";
}
else
{
LabelTxt = "Foo ";
}
});
}
}
}
This way you also see how to bind button for example. Press the button to see that the update is well done.
If using same directories than me, remember to edit app.xaml to use StartupUri="Views/MainWindow.xaml">
instead of
StartupUri="MainWindow.xaml">
edited Nov 16 '18 at 10:24
answered Nov 15 '18 at 16:59
MikitoriMikitori
522820
522820
Thank you for your answer. This ViewModelBase was a really great idea, I just start to think in this way, when I am programming. So I created that BaseViewModel what you suggested with three function. I used three function because I really do not understand how are these works. I have got two function from your example, and I also add the function what we used earlier in this project. I will edit the post, you can see there. What are the functions doing? Still not working. Which function should I bind to which XAML property to get it work?
– AME
Nov 15 '18 at 17:22
2 issues, you shouldn't need the OnPropertyChanged, it's already handled by the code I provided. The really big issue in your modification is : set { SetAndRaisePropertyChanged(ref _balance, "1111$"); } you really need to keep the code I posted. the word value is a key word and means the value you provided to set yourt property. take my code and then you can set your property like a classical variable: Balance = "1111$"; if you want to initialize with a default value, you do it on the private part: private String _mBalance = String.Empty; for example
– Mikitori
Nov 15 '18 at 21:04
For the datacontext (you are setting it in the xaml) your way may work but I think you can do it better. Maybe tomorrow i can share more code if needed but try what I said, it should be ok.
– Mikitori
Nov 15 '18 at 21:07
Still not figured it out, how to get it work, so i would appreciate it.
– AME
Nov 16 '18 at 8:11
Full example added ;)
– Mikitori
Nov 16 '18 at 10:24
|
show 3 more comments
Thank you for your answer. This ViewModelBase was a really great idea, I just start to think in this way, when I am programming. So I created that BaseViewModel what you suggested with three function. I used three function because I really do not understand how are these works. I have got two function from your example, and I also add the function what we used earlier in this project. I will edit the post, you can see there. What are the functions doing? Still not working. Which function should I bind to which XAML property to get it work?
– AME
Nov 15 '18 at 17:22
2 issues, you shouldn't need the OnPropertyChanged, it's already handled by the code I provided. The really big issue in your modification is : set { SetAndRaisePropertyChanged(ref _balance, "1111$"); } you really need to keep the code I posted. the word value is a key word and means the value you provided to set yourt property. take my code and then you can set your property like a classical variable: Balance = "1111$"; if you want to initialize with a default value, you do it on the private part: private String _mBalance = String.Empty; for example
– Mikitori
Nov 15 '18 at 21:04
For the datacontext (you are setting it in the xaml) your way may work but I think you can do it better. Maybe tomorrow i can share more code if needed but try what I said, it should be ok.
– Mikitori
Nov 15 '18 at 21:07
Still not figured it out, how to get it work, so i would appreciate it.
– AME
Nov 16 '18 at 8:11
Full example added ;)
– Mikitori
Nov 16 '18 at 10:24
Thank you for your answer. This ViewModelBase was a really great idea, I just start to think in this way, when I am programming. So I created that BaseViewModel what you suggested with three function. I used three function because I really do not understand how are these works. I have got two function from your example, and I also add the function what we used earlier in this project. I will edit the post, you can see there. What are the functions doing? Still not working. Which function should I bind to which XAML property to get it work?
– AME
Nov 15 '18 at 17:22
Thank you for your answer. This ViewModelBase was a really great idea, I just start to think in this way, when I am programming. So I created that BaseViewModel what you suggested with three function. I used three function because I really do not understand how are these works. I have got two function from your example, and I also add the function what we used earlier in this project. I will edit the post, you can see there. What are the functions doing? Still not working. Which function should I bind to which XAML property to get it work?
– AME
Nov 15 '18 at 17:22
2 issues, you shouldn't need the OnPropertyChanged, it's already handled by the code I provided. The really big issue in your modification is : set { SetAndRaisePropertyChanged(ref _balance, "1111$"); } you really need to keep the code I posted. the word value is a key word and means the value you provided to set yourt property. take my code and then you can set your property like a classical variable: Balance = "1111$"; if you want to initialize with a default value, you do it on the private part: private String _mBalance = String.Empty; for example
– Mikitori
Nov 15 '18 at 21:04
2 issues, you shouldn't need the OnPropertyChanged, it's already handled by the code I provided. The really big issue in your modification is : set { SetAndRaisePropertyChanged(ref _balance, "1111$"); } you really need to keep the code I posted. the word value is a key word and means the value you provided to set yourt property. take my code and then you can set your property like a classical variable: Balance = "1111$"; if you want to initialize with a default value, you do it on the private part: private String _mBalance = String.Empty; for example
– Mikitori
Nov 15 '18 at 21:04
For the datacontext (you are setting it in the xaml) your way may work but I think you can do it better. Maybe tomorrow i can share more code if needed but try what I said, it should be ok.
– Mikitori
Nov 15 '18 at 21:07
For the datacontext (you are setting it in the xaml) your way may work but I think you can do it better. Maybe tomorrow i can share more code if needed but try what I said, it should be ok.
– Mikitori
Nov 15 '18 at 21:07
Still not figured it out, how to get it work, so i would appreciate it.
– AME
Nov 16 '18 at 8:11
Still not figured it out, how to get it work, so i would appreciate it.
– AME
Nov 16 '18 at 8:11
Full example added ;)
– Mikitori
Nov 16 '18 at 10:24
Full example added ;)
– Mikitori
Nov 16 '18 at 10:24
|
show 3 more comments
Have you properly set the DataContext on the window/control to your view model? You need to set your DataContext before you are able to use bindings. And as such, you should probably use the proper way for binding:
<Label Content="{Binding Balance}" ... />
Edit:
Okay, I'll give you a concrete example of what I mean. Also, you're going to run into a lot of issues using a view model as a StaticResource
. Why do I say this? Because once you start adding dependencies to your view model (accessing business logic, etc), you will need some form of dependency injection (DI) or a similar way to do so.
So you have your ViewModelBase
, so I'll use that and not duplicate myself. Here's a simple view model:
public class AccountViewModel : ViewModelBase
{
string _balance = "1111$";
public AccountViewModel(string accountNumber)
{
AccountNumber = accountNumber;
}
public string AccountNumber { get; }
public string Balance
{
get { return _balance; }
set { SetAndRaisePropertyChanged(ref _balance, value); }
}
}
Here's the view code (MainWindow.xaml
):
<Window x:Class="testProj.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008">
<Grid>
<Label Content="{Binding Balance}" />
</Grid>
</Window>
And the code behind (MainWindow.xaml.cs
):
public partial class MainWindow
{
public MainWindow(AccountViewModel dataContext)
{
DataContext = dataContext;
InitializeComponent();
}
}
And for fun, the App.xaml.cs
(set up for BuildAction - Page):
public partial class App
{
[STAThread]
public static void Main(string args)
{
new MainWindow(new AccountViewModel("123456789")).ShowDialog();
}
}
This will show you what you are expecting, and display the Balance correctly. There are a few things you can try to see what your issue is:
- Is there any information in the output window when debugging that tells you if a binding error is occurring?
Can you give a shorter version of your application showing all parts (i.e. a short project that duplicates the issue) and upload it somewhere?
I do not know what do you mean by DataContext, but I updated the the XAML code and you can see there how did I bind the ViewModel to the View.
– AME
Nov 15 '18 at 18:37
Anyway I tried your code, and still not working, In my opinion it is doing the same.
– AME
Nov 15 '18 at 18:40
Maybe I was not clear. So the binding is works fine when I update the view, but when I first open the window, it won't display the initial value of the property, just after I trigger it with an update
– AME
Nov 17 '18 at 14:08
Have you tried using the Live Visual Tree explorer in Visual Studio to inspect the label and see what itsContent
property is initially? What debugging steps have you taken to validate that the Balance property is initialized properly to have the value you've expected?
– RecursiveNerd
Nov 19 '18 at 20:01
The margin was the problem. :)
– AME
Nov 20 '18 at 18:19
add a comment |
Have you properly set the DataContext on the window/control to your view model? You need to set your DataContext before you are able to use bindings. And as such, you should probably use the proper way for binding:
<Label Content="{Binding Balance}" ... />
Edit:
Okay, I'll give you a concrete example of what I mean. Also, you're going to run into a lot of issues using a view model as a StaticResource
. Why do I say this? Because once you start adding dependencies to your view model (accessing business logic, etc), you will need some form of dependency injection (DI) or a similar way to do so.
So you have your ViewModelBase
, so I'll use that and not duplicate myself. Here's a simple view model:
public class AccountViewModel : ViewModelBase
{
string _balance = "1111$";
public AccountViewModel(string accountNumber)
{
AccountNumber = accountNumber;
}
public string AccountNumber { get; }
public string Balance
{
get { return _balance; }
set { SetAndRaisePropertyChanged(ref _balance, value); }
}
}
Here's the view code (MainWindow.xaml
):
<Window x:Class="testProj.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008">
<Grid>
<Label Content="{Binding Balance}" />
</Grid>
</Window>
And the code behind (MainWindow.xaml.cs
):
public partial class MainWindow
{
public MainWindow(AccountViewModel dataContext)
{
DataContext = dataContext;
InitializeComponent();
}
}
And for fun, the App.xaml.cs
(set up for BuildAction - Page):
public partial class App
{
[STAThread]
public static void Main(string args)
{
new MainWindow(new AccountViewModel("123456789")).ShowDialog();
}
}
This will show you what you are expecting, and display the Balance correctly. There are a few things you can try to see what your issue is:
- Is there any information in the output window when debugging that tells you if a binding error is occurring?
Can you give a shorter version of your application showing all parts (i.e. a short project that duplicates the issue) and upload it somewhere?
I do not know what do you mean by DataContext, but I updated the the XAML code and you can see there how did I bind the ViewModel to the View.
– AME
Nov 15 '18 at 18:37
Anyway I tried your code, and still not working, In my opinion it is doing the same.
– AME
Nov 15 '18 at 18:40
Maybe I was not clear. So the binding is works fine when I update the view, but when I first open the window, it won't display the initial value of the property, just after I trigger it with an update
– AME
Nov 17 '18 at 14:08
Have you tried using the Live Visual Tree explorer in Visual Studio to inspect the label and see what itsContent
property is initially? What debugging steps have you taken to validate that the Balance property is initialized properly to have the value you've expected?
– RecursiveNerd
Nov 19 '18 at 20:01
The margin was the problem. :)
– AME
Nov 20 '18 at 18:19
add a comment |
Have you properly set the DataContext on the window/control to your view model? You need to set your DataContext before you are able to use bindings. And as such, you should probably use the proper way for binding:
<Label Content="{Binding Balance}" ... />
Edit:
Okay, I'll give you a concrete example of what I mean. Also, you're going to run into a lot of issues using a view model as a StaticResource
. Why do I say this? Because once you start adding dependencies to your view model (accessing business logic, etc), you will need some form of dependency injection (DI) or a similar way to do so.
So you have your ViewModelBase
, so I'll use that and not duplicate myself. Here's a simple view model:
public class AccountViewModel : ViewModelBase
{
string _balance = "1111$";
public AccountViewModel(string accountNumber)
{
AccountNumber = accountNumber;
}
public string AccountNumber { get; }
public string Balance
{
get { return _balance; }
set { SetAndRaisePropertyChanged(ref _balance, value); }
}
}
Here's the view code (MainWindow.xaml
):
<Window x:Class="testProj.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008">
<Grid>
<Label Content="{Binding Balance}" />
</Grid>
</Window>
And the code behind (MainWindow.xaml.cs
):
public partial class MainWindow
{
public MainWindow(AccountViewModel dataContext)
{
DataContext = dataContext;
InitializeComponent();
}
}
And for fun, the App.xaml.cs
(set up for BuildAction - Page):
public partial class App
{
[STAThread]
public static void Main(string args)
{
new MainWindow(new AccountViewModel("123456789")).ShowDialog();
}
}
This will show you what you are expecting, and display the Balance correctly. There are a few things you can try to see what your issue is:
- Is there any information in the output window when debugging that tells you if a binding error is occurring?
Can you give a shorter version of your application showing all parts (i.e. a short project that duplicates the issue) and upload it somewhere?
Have you properly set the DataContext on the window/control to your view model? You need to set your DataContext before you are able to use bindings. And as such, you should probably use the proper way for binding:
<Label Content="{Binding Balance}" ... />
Edit:
Okay, I'll give you a concrete example of what I mean. Also, you're going to run into a lot of issues using a view model as a StaticResource
. Why do I say this? Because once you start adding dependencies to your view model (accessing business logic, etc), you will need some form of dependency injection (DI) or a similar way to do so.
So you have your ViewModelBase
, so I'll use that and not duplicate myself. Here's a simple view model:
public class AccountViewModel : ViewModelBase
{
string _balance = "1111$";
public AccountViewModel(string accountNumber)
{
AccountNumber = accountNumber;
}
public string AccountNumber { get; }
public string Balance
{
get { return _balance; }
set { SetAndRaisePropertyChanged(ref _balance, value); }
}
}
Here's the view code (MainWindow.xaml
):
<Window x:Class="testProj.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008">
<Grid>
<Label Content="{Binding Balance}" />
</Grid>
</Window>
And the code behind (MainWindow.xaml.cs
):
public partial class MainWindow
{
public MainWindow(AccountViewModel dataContext)
{
DataContext = dataContext;
InitializeComponent();
}
}
And for fun, the App.xaml.cs
(set up for BuildAction - Page):
public partial class App
{
[STAThread]
public static void Main(string args)
{
new MainWindow(new AccountViewModel("123456789")).ShowDialog();
}
}
This will show you what you are expecting, and display the Balance correctly. There are a few things you can try to see what your issue is:
- Is there any information in the output window when debugging that tells you if a binding error is occurring?
Can you give a shorter version of your application showing all parts (i.e. a short project that duplicates the issue) and upload it somewhere?
edited Nov 16 '18 at 19:34
answered Nov 15 '18 at 18:26
RecursiveNerdRecursiveNerd
113
113
I do not know what do you mean by DataContext, but I updated the the XAML code and you can see there how did I bind the ViewModel to the View.
– AME
Nov 15 '18 at 18:37
Anyway I tried your code, and still not working, In my opinion it is doing the same.
– AME
Nov 15 '18 at 18:40
Maybe I was not clear. So the binding is works fine when I update the view, but when I first open the window, it won't display the initial value of the property, just after I trigger it with an update
– AME
Nov 17 '18 at 14:08
Have you tried using the Live Visual Tree explorer in Visual Studio to inspect the label and see what itsContent
property is initially? What debugging steps have you taken to validate that the Balance property is initialized properly to have the value you've expected?
– RecursiveNerd
Nov 19 '18 at 20:01
The margin was the problem. :)
– AME
Nov 20 '18 at 18:19
add a comment |
I do not know what do you mean by DataContext, but I updated the the XAML code and you can see there how did I bind the ViewModel to the View.
– AME
Nov 15 '18 at 18:37
Anyway I tried your code, and still not working, In my opinion it is doing the same.
– AME
Nov 15 '18 at 18:40
Maybe I was not clear. So the binding is works fine when I update the view, but when I first open the window, it won't display the initial value of the property, just after I trigger it with an update
– AME
Nov 17 '18 at 14:08
Have you tried using the Live Visual Tree explorer in Visual Studio to inspect the label and see what itsContent
property is initially? What debugging steps have you taken to validate that the Balance property is initialized properly to have the value you've expected?
– RecursiveNerd
Nov 19 '18 at 20:01
The margin was the problem. :)
– AME
Nov 20 '18 at 18:19
I do not know what do you mean by DataContext, but I updated the the XAML code and you can see there how did I bind the ViewModel to the View.
– AME
Nov 15 '18 at 18:37
I do not know what do you mean by DataContext, but I updated the the XAML code and you can see there how did I bind the ViewModel to the View.
– AME
Nov 15 '18 at 18:37
Anyway I tried your code, and still not working, In my opinion it is doing the same.
– AME
Nov 15 '18 at 18:40
Anyway I tried your code, and still not working, In my opinion it is doing the same.
– AME
Nov 15 '18 at 18:40
Maybe I was not clear. So the binding is works fine when I update the view, but when I first open the window, it won't display the initial value of the property, just after I trigger it with an update
– AME
Nov 17 '18 at 14:08
Maybe I was not clear. So the binding is works fine when I update the view, but when I first open the window, it won't display the initial value of the property, just after I trigger it with an update
– AME
Nov 17 '18 at 14:08
Have you tried using the Live Visual Tree explorer in Visual Studio to inspect the label and see what its
Content
property is initially? What debugging steps have you taken to validate that the Balance property is initialized properly to have the value you've expected?– RecursiveNerd
Nov 19 '18 at 20:01
Have you tried using the Live Visual Tree explorer in Visual Studio to inspect the label and see what its
Content
property is initially? What debugging steps have you taken to validate that the Balance property is initialized properly to have the value you've expected?– RecursiveNerd
Nov 19 '18 at 20:01
The margin was the problem. :)
– AME
Nov 20 '18 at 18:19
The margin was the problem. :)
– AME
Nov 20 '18 at 18:19
add a comment |
Delete the margin solved the problem. I guess the margin pushed out the label.
add a comment |
Delete the margin solved the problem. I guess the margin pushed out the label.
add a comment |
Delete the margin solved the problem. I guess the margin pushed out the label.
Delete the margin solved the problem. I guess the margin pushed out the label.
answered Nov 22 '18 at 18:28
AMEAME
555
555
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53324293%2fwhy-does-not-display-the-content-of-the-label%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
you understood well the issue and you were on the right path, see my answer for more ^^
– Mikitori
Nov 15 '18 at 17:00