<Window x:Class="RMT_MMO.Starter.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="304" Width="472"
ResizeMode="NoResize">
<Grid Margin="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100*"/>
<ColumnDefinition Width="200*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="50*"/>
<RowDefinition Height="10*"/>
<RowDefinition Height="40*"/>
<RowDefinition Height="40*"/>
<RowDefinition Height="80*"/>
</Grid.RowDefinitions>
<ProgressBar Grid.ColumnSpan="2" Maximum="100" Value="{Binding Percent}"/>
<Label Grid.ColumnSpan="2" Content="{Binding Status }" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" FontSize="14" FontWeight="Bold" Margin="0,0,0,10"/>
<Label Grid.Row="2" Content="Username" HorizontalContentAlignment="Right" VerticalContentAlignment="Center" FontSize="14" FontWeight="Bold"/>
<TextBox IsEnabled="{Binding CanLogin}" Grid.Row="2" Grid.Column="1" Margin="5" Text="{Binding Username}" HorizontalContentAlignment="Center" VerticalContentAlignment="Center"/>
<Label Grid.Row="3" Content="Password" HorizontalContentAlignment="Right" VerticalContentAlignment="Center" FontSize="14" FontWeight="Bold"/>
<PasswordBox IsEnabled="{Binding CanLogin}" Grid.Row="3" Grid.Column="1" Margin="5" x:Name="Password" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" />
<Button Click="Login" IsDefault="True" IsEnabled="{Binding CanLogin}" Content="asdasd" Grid.Row="4" HorizontalAlignment="Left" Padding="10" Margin="10,25,0,19" RenderTransformOrigin="7.273,0.484" Width="247" Grid.Column="1"/>
</Grid>
</Window>
So here how MainWindow look, when I click to button this code execute
using System.Windows;
namespace RMT_MMO.Starter
{
public partial class MainWindow
{
private readonly MainWindowViewModel _viewModel;
public MainWindow()
{
InitializeComponent();
_viewModel = new MainWindowViewModel();
DataContext = _viewModel;
_viewModel.CanLogin = true;
}
public void Login(object sender,RoutedEventArgs e)
{
// MessageBox.Show(_viewModel.Percent.ToString());
_viewModel.CanLogin = false;
_viewModel.Percent =50;
// _viewModel.Status = "Stuff happened";
}
}
}
And MainWindowViewModel class looks like this:
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace RMT_MMO.Starter
{
public class MainWindowViewModel:INotifyPropertyChanging
{
private bool _canLogin;
private string _status;
private double _percent;
private string _username;
public event PropertyChangingEventHandler PropertyChanging;
public bool CanLogin
{
get { return _canLogin; }
set
{
_canLogin = value;
OnPropertyChanged();
}
}
public string Status
{
get { return _status; }
set
{
_status = value;
OnPropertyChanged();
}
}
public double Percent
{
get { return _percent; }
set
{
_percent = value;
OnPropertyChanged();
}
}
public string Username
{
get { return _username; }
set
{
_username = value;
OnPropertyChanged();
}
}
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanging;
if (handler != null)
handler(this, new PropertyChangingEventArgs(propertyName));
}
}
}
What I am trying to do is to bind xmla and this code, when I hit button binding is not performed.
I know it it is trivial mistake but I simple can't fined it, I tried searching online but I failed. All help is welcome.
It could be because you are using INotifyPropertyChanging when you should be using INotifyPropertyChanged interface.
Related
I have a user list in MainWindow. After pressing the preview button, a non-modal window for data editing opens. Updated data are changed in real time in the main window. The question is how to bind the windows so that because the user changes from the list in the main window, he changes in real time in an already open non-modal window.
WPF does not recommend coding business logic directly in xaml.cs
files.
It is recommended that you write code using the MVVM pattern
ViewModel
public class podgladUzytkownika : INotifyPropertyChanged
{
private string imie;
private string nazwisko;
private string mail;
public string Mail
{
get => mail;
set => this.SetValue(ref mail, value);
}
public string Nazwisko
{
get => nazwisko;
set => this.SetValue(ref nazwisko, value);
}
public string Imie
{
get => imie;
set => this.SetValue(ref imie, value);
}
public event PropertyChangedEventHandler PropertyChanged;
protected void SetValue<T>(ref T oldValue, T newValue, [CallerMemberName] string propertyName = null)
{
oldValue = newValue;
OnPropertyChanged(propertyName);
}
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public class MainWindowViewModel
{
private int refreshCount;
public ICommand RefreshCommand { get; }
public ICommand PodgladUzytkownikaShow { get; }
public podgladUzytkownika data { get; }
public MainWindowViewModel()
{
data = new podgladUzytkownika();
PodgladUzytkownikaShow = new Command(PodgladUzytkownikaShowExecute);
RefreshCommand = new Command(RefreshCommandExecute);
}
private void PodgladUzytkownikaShowExecute(object obj)
{
var window = new Window();
window.DataContext = data;
window.Show();
}
private void RefreshCommandExecute(object obj)
{
// Data updates are passed to the view
refreshCount++;
data.Imie = nameof(data.Imie) + refreshCount;
data.Nazwisko = nameof(data.Nazwisko) + refreshCount;
data.Mail = nameof(data.Mail) + refreshCount;
}
}
View
// MainWindow.xaml
<StackPanel x:Name="StackPanel1">
<Button Content="PodgladUzytkownika" Command="{Binding Path=PodgladUzytkownikaShow}"/>
<Button Content="Refresh" Command="{Binding Path=RefreshCommand}"/>
</StackPanel>
// window.xaml
<StackPanel >
<TextBlock Text="{Binding Path=Imie }"/>
<TextBlock Text="{Binding Path=Nazwisko }"/>
<TextBlock Text="{Binding Path=Mail }"/>
</StackPanel>
Demo
this.MainWindow.DataContext =new MainWindowViewModel();
After chasing one problem after another with your comments, the problem is your code is not well-designed. Using data bindings (one of the prime benefits of WPF), you can stop chasing your tail with trying to figure out how to update one UI when data changes. Here is a simplified version of your code that will always ensure the UI matches the data you wish to manipulate.
MainWindow.xaml
<Grid Margin="3">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<Label Margin="3" Grid.ColumnSpan="3">Lista użytkowników</Label>
<Button Margin="3" Padding="3" Grid.Row="2" Grid.ColumnSpan="3" Click="Zamknij_Click">Zamknij</Button>
<StackPanel Margin="3" Grid.Column="2" Grid.Row="1">
<!--<Button Name="Dodaj" Click="Dodaj_Click" Margin="3" Padding="10,3" >Dodaj...</Button>-->
<!--<Button Name="Usun" IsEnabled="False" Click="Usun_Click" Margin="3" Padding="10,3" >Usuń</Button>-->
<!--<Button Name="Edytuj" IsEnabled="False" Click="Edytuj_Click" Margin="3" Padding="10,3" >Edytuj...</Button>-->
<Button Name="Podglad" IsEnabled="False" Click="Podglad_Click" Margin="3" Padding="10,3" >Podgląd...</Button>
</StackPanel>
<ListView SelectionMode="Single" SelectionChanged="Selection_Changed" Name="lv_uzytkownicy" Margin="3" Grid.Row="1">
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn Header="Imię"
DisplayMemberBinding="{Binding Imie}"/>
<GridViewColumn Header="Nazwisko"
DisplayMemberBinding="{Binding Nazwisko}" />
<GridViewColumn Header="Mail"
DisplayMemberBinding="{Binding Mail}"/>
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
<GridSplitter Grid.Column="1" Grid.Row="1" Width="5" ResizeDirection="Columns" HorizontalAlignment="Center"/>
</Grid>
MainWindow.xaml.cs
using System.Collections.ObjectModel;
public partial class MainWindow : Window
{
public ObservableCollection<Uzytkownik> listaUzytkownikow = new ObservableCollection<Uzytkownik>();
Podglad_Uzytkownika podgladUzytkownika;
public MainWindow()
{
InitializeComponent();
lv_uzytkownicy.ItemsSource = listaUzytkownikow;
listaUzytkownikow.Add(new Uzytkownik("Mietek", "Żul", "sikalafa#wp.pl"));
listaUzytkownikow.Add(new Uzytkownik("Franek", "Alpinista", "halo#gmail.pl"));
listaUzytkownikow.Add(new Uzytkownik("Stefan", "Ulążka", "mam.to#o2.pl"));
this.DataContext = this;
}
private void Podglad_Click(object sender, RoutedEventArgs e)
{
podgladUzytkownika = new Podglad_Uzytkownika();
podgladUzytkownika.DataContext = lv_uzytkownicy.SelectedItem;
podgladUzytkownika.Show();
}
private void Zamknij_Click(object sender, RoutedEventArgs e)
{
Close();
}
private void Selection_Changed(object sender, SelectionChangedEventArgs e)
{
if (lv_uzytkownicy.SelectedItems.Count > 0) Podglad.IsEnabled = true;
else Podglad.IsEnabled = false;
if (podgladUzytkownika != null && podgladUzytkownika.IsVisible)
{
podgladUzytkownika.DataContext = lv_uzytkownicy.SelectedItem;
}
}
}
Podglad_Uzytkownika.xaml
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Label Margin="3">Imię</Label>
<Label Margin="3" Grid.Row="1">Nazwisko</Label>
<Label Margin="3" Grid.Row="2">Email</Label>
<TextBox Name="imieTextBox" Text="{Binding Imie, UpdateSourceTrigger=PropertyChanged}" Margin="3" Grid.Column="1"/>
<TextBox Name="nazwiskoTextBox" Text="{Binding Nazwisko, UpdateSourceTrigger=PropertyChanged}" Margin="3" Grid.Column="1" Grid.Row="1"/>
<TextBox Name="mailTextBox" Text="{Binding Mail, UpdateSourceTrigger=PropertyChanged}" Margin="3" Grid.Column="1" Grid.Row="2"/>
<Grid HorizontalAlignment="Center" Grid.ColumnSpan="2" Grid.Row="3" Grid.IsSharedSizeScope="True">
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="pierwsza" />
</Grid.ColumnDefinitions>
<Button Margin="3" Padding="20, 5" Name="Podglad" Click="Podglad_Click" IsDefault="True">Zamknij</Button>
</Grid>
</Grid>
Podglad_Uzytkownika.xaml.cs
public partial class Podglad_Uzytkownika : Window
{
public Podglad_Uzytkownika()
{
InitializeComponent();
}
private void Podglad_Click(object sender, RoutedEventArgs e)
{
Close();
}
}
Uzytkownik.cs
public class Uzytkownik : INotifyPropertyChanged
{
private string imie;
private string nazwisko;
private string mail;
public Uzytkownik(string imie, string nazwisko, string mail)
{
this.Imie = imie;
this.Nazwisko = nazwisko;
this.Mail = mail;
}
public string Imie { get => this.imie; set { this.imie = value; OnPropertyChanged(); } }
public string Nazwisko { get => this.nazwisko; set { this.nazwisko = value; OnPropertyChanged(); } }
public string Mail { get => this.mail; set { this.mail = value; OnPropertyChanged(); } }
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
I am still new in MVVM and WPF
and I've looked at some examples however still did not found exactly the answers to my question.
I have a ListBox which each Item should add a new user control using ObservableCollection. In the user control I have an several Text blocks which I want to bound the texts of them to the same ObservableCollection which contain the Data.
However I am not sure how to bind the Text blocks to the ObservableCollection
Would be happy for a code example.
I'm also attaching my code, this is my userControl XAML:
<UserControl x:Class="ProtocolAnalyzerGui.UserControlls.MenuControlls.UCSingleLine"
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"
mc:Ignorable="d"
d:DesignHeight="100" d:DesignWidth="300">
<Grid Background="#FF454545">
<Grid.RowDefinitions>
<RowDefinition Height="1*"></RowDefinition>
<RowDefinition Height="1*"></RowDefinition>
</Grid.RowDefinitions>
<TextBlock x:Name="TBHeader" Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Center" ></TextBlock>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"></ColumnDefinition>
<ColumnDefinition Width="10"></ColumnDefinition>
<ColumnDefinition Width="1*"></ColumnDefinition>
<ColumnDefinition Width="10"></ColumnDefinition>
<ColumnDefinition Width="1*"></ColumnDefinition>
<ColumnDefinition Width="10"></ColumnDefinition>
<ColumnDefinition Width="1*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock x:Name="TBDatanTime" Grid.Column="0" Foreground="White" Text="{Binding DataAndTime }" ></TextBlock>
<TextBlock x:Name="TBComPort" Grid.Column="2" Foreground="White" Text="{Binding ComPort }" ></TextBlock>
<TextBlock x:Name="TBTranslation" Grid.Column="4" Foreground="White" Text="{Binding Translation }" ></TextBlock>
<TextBlock x:Name="TBDataBytesArray" Grid.Column="6" Foreground="White" Text="{Binding Header }" ></TextBlock>
</Grid>
</Grid>
</UserControl>
in the main window XAML:
<ScrollViewer Grid.Row="3" HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto">
<ListBox x:Name="LBListBox">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<myControlls:UCSingleLine x:Name="DataUserContoll"
DataContext="{Binding DataForGui}"></myControlls:UCSingleLine>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</ScrollViewer>
the binding of the listbox Itemsource is inside this function:
private void MI_SerialPortStart_Click(object sender, RoutedEventArgs e)
{
LBListBox.ItemsSource = DataForGui;
_SerialPortTakeCare.Start();
}
also attaching my dataCode:
public class Data : INotifyPropertyChanged
{
private string _DataAndTime;
public string DataAndTime
{
get { return _DataAndTime; }
set
{
_DataAndTime = value;
OnPropertyChanged("DataAndTime");
}
}
private string _ComPort;
public string ComPort
{
get { return _ComPort; }
set
{
_ComPort = value;
OnPropertyChanged("ComPort");
}
}
private string _Translation;
public string Translation
{
get { return _Translation; }
set
{
_Translation = value;
OnPropertyChanged("Translation");
}
}
private string _Header;
public string Header
{
get { return _Header; }
set
{
_Header = value;
OnPropertyChanged("Header");
}
}
private string _Data_ARR;
public string Data_ARR
{
get { return _Data_ARR; }
set
{
_Data_ARR = value;
OnPropertyChanged("Data_ARR");
}
}
public Data()
{
_ComPort = "";
_Data_ARR = "";
_DataAndTime = "";
_Header = "";
_Translation = "";
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
You just need to set the data context of your user control and then add the appropriate bindings.
In your main window, this line should look as follows:
<local:UserControl1 DataContext="{Binding}" x:Name="DataUserContoll"/>
And in the user control, the code should look more like this:
<TextBlock x:Name="TBDatanTime" Grid.Column="0" Foreground="White" Text="{Binding TextField1}" />
<TextBlock x:Name="TBComPort" Grid.Column="2" Foreground="White" Text="{Binding TextField2}"/>
<TextBlock x:Name="TBTranslation" Grid.Column="4" Foreground="White" Text="{Binding TextField3}"/>
<TextBlock x:Name="TBDataBytesArray" Grid.Column="6" Foreground="White" Text="{Binding TextField4}"/>
... and you should change the placeholder field names I have put in (e.g. "TextField1") to be the actual string properties of the objects inside your collection "DataForGui".
I'm need to show data from ViewModel in simple grid which contain labels and textBlock for data. I'm try to bind data to grid and use ElementName to bind grid's DataContext with textBlocks.
Book ViewModel:
namespace Books.ViewModels
{
public class BookViewModel : IViewModel, INotifyPropertyChanged
{
private Book book = new Book();
private ICommand AddCommand;
private ICommand RemoveCommand;
private ICommand ChangeCommand;
public event PropertyChangedEventHandler PropertyChanged;
public BookViewModel()
{
//initialize commands;
}
public string Name
{
get { return book.Name; }
set { book.Name = value; }
}
public string Authors
{
get
{
return string.Join(", ", book.Authors.Select(x => x.Name));
}
set
{
//need to implemented
}
}
public string ISBN
{
get { return book.ISBN; }
set { book.ISBN = value; }
}
public int Pages
{
get { return book.Pages; }
set { book.Pages = value; }
}
public string Tags
{
get
{
return string.Join(", ", book.Tags);
}
set
{
//not implemented
}
}
public int PublicationYear
{
get { return book.PublicationYear; }
set { book.PublicationYear = value; }
}
public string House
{
get
{
return book.House.Name;
}
set
{
//not implemented
}
}
public ICommand AddClick
{
get
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Add"));
return AddCommand;
}
}
public ICommand RemoveClick
{
get
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Remove"));
return RemoveCommand;
}
}
public ICommand ChangeClick
{
get
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Change"));
return ChangeCommand;
}
}
}
}
grid in Xaml:
<Grid x:Name="bookGrid"
Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Content="Title:"/>
<Label Grid.Row="1" Grid.Column="0" Content="Author(s):"/>
<Label Grid.Row="2" Grid.Column="0" Content="ISBN:"/>
<Label Grid.Row="3" Grid.Column="0" Content="Pages:"/>
<Label Grid.Row="4" Grid.Column="0" Content="Tags:"/>
<Label Grid.Row="5" Grid.Column="0" Content="Publication Year:"/>
<Label Grid.Row="6" Grid.Column="0" Content="Publication House:"/>
<TextBlock Grid.Column="1" Grid.Row="0" Margin="3" Text="{Binding ElementName=bookGrid, Path=Name}"/>
<TextBlock Grid.Column="1" Grid.Row="1" Margin="3" Text="{Binding ElementName=bookGrid, Path=Authors}"/>
<TextBlock Grid.Column="1" Grid.Row="2" Margin="3" Text="{Binding ElementName=bookGrid, Path=ISBN}"/>
<TextBlock Grid.Column="1" Grid.Row="3" Margin="3" Text="{Binding ElementName=bookGrid, Path=Pages}"/>
<TextBlock Grid.Column="1" Grid.Row="4" Margin="3" Text="{Binding ElementName=bookGrid, Path=Tags}"/>
<TextBlock Grid.Column="1" Grid.Row="5" Margin="3" Text="{Binding ElementName=bookGrid, Path=PublicationYear}"/>
<TextBlock Grid.Column="1" Grid.Row="6" Margin="3" Text="{Binding ElementName=bookGrid, Path=House}"/>
</Grid>
Code behind:
bookGrid.DataContext = Manager.books.First();
Just change the TextBlock bindings to something like:
<TextBlock Grid.Column="1" Grid.Row="0" Margin="3" Text="{Binding Name}"/>
Add a notifier method tho the viewmodel:
public void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
And call this method after each property change like:
public string Name
{
get { return book.Name; }
set
{
book.Name = value;
this.NotifyPropertyChanged();
}
}
On my WPF app page i have 2 bindings
1. for a list of items as an observable collection
2. just to show some values on a lable using binding
My class struct like this
public DbVersionModel DbVersion { get; set; }
public ObservableCollection<BookStore> StoreCollection
{ get { return thisApp.app_Stores; } }
public class DbVersionModel : INotifyPropertyChanged
{
private int _LocalVersion { get; set; }
private int _ServerVersion { get; set; }
private int _ActiveStores { get; set; }
private string _LastModifiedLocal { get; set; }
private string _LastModifiedServer { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyChange(PropertyChangedEventArgs e)
{
if (PropertyChanged != null)
PropertyChanged(this, e);
}
public int LocalVersion
{
get { return _LocalVersion; }
set
{
_LocalVersion = value;
NotifyChange(new PropertyChangedEventArgs("LocalVersion"));
}
}
public int ServerVersion
{
get { return _ServerVersion; }
set
{
_ServerVersion = value;
NotifyChange(new PropertyChangedEventArgs("ServerVersion"));
}
}
public int ActiveStores
{
get { return _ActiveStores; }
set
{
_ActiveStores = value;
NotifyChange(new PropertyChangedEventArgs("ActiveStores"));
}
}
public string LastModifiedLocal
{
get { return _LastModifiedLocal; }
set
{
_LastModifiedLocal = value;
NotifyChange(new PropertyChangedEventArgs("LastModifiedLocal"));
}
}
public string LastModifiedServer
{
get { return _LastModifiedServer; }
set
{
_LastModifiedServer = value;
NotifyChange(new PropertyChangedEventArgs("LastModifiedServer"));
}
}
} public ManagePage()
{
InitializeComponent();
setContext();
}
private void setContext()
{
try
{
DbVersionModel db_version = new DbVersionModel();
db_version.LastModifiedServer = //set with value;
db_version.ServerVersion = //set with value;
db_version.LocalVersion = //set with value;
db_version.LastModifiedLocal = //set with value;
db_version.ActiveStores = //set with value;
this.DbVersion = db_version;
}
catch
{
}
}
xaml like this
<Page x:Class="App.ManagePage"
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"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
mc:Ignorable="d">
<Page.Resources>
</Page.Resources>
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" >
<Grid Margin="5 10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"></ColumnDefinition>
<ColumnDefinition ></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<!--// -->
<Label Content="Active stores[Local]" Grid.Column="0" Grid.Row="0" ></Label>
<Label Content="{Binding Source=DbVersion, Path=ActiveStores}" Grid.Column="1" Grid.Row="0" ></Label>
<Label Content="Current version [Local]" Grid.Column="0" Grid.Row="1" ></Label>
<Label Content="{Binding Source=DbVersion, Path=LocalVersion}" Grid.Column="1" Grid.Row="1" ></Label>
<Label Content="Curretn Version [Server]" Grid.Column="0" Grid.Row="2" ></Label>
<Label Content="{Binding Source=DbVersion, Path=ServerVersion}" Grid.Column="1" Grid.Row="2" ></Label>
<Label Content="Last modified [Local]" Grid.Column="0" Grid.Row="3" ></Label>
<Label Content="{Binding Source=DbVersion, Path=LastModifiedLocal}" Grid.Column="1" Grid.Row="3" ></Label>
<Label Content="Last modified [Server]" Grid.Column="0" Grid.Row="4" ></Label>
<Label Content="{Binding Source=DbVersion, Path=LastModifiedServer}" Grid.Column="1" Grid.Row="4" ></Label>
<StackPanel Grid.Column="0" Grid.ColumnSpan="5" Grid.Row="6" HorizontalAlignment="Center">
<Button Name="btnSync" Content="Sync stores" Height="30" Click="btnSync_Click" Style="{StaticResource ActionButtons}"></Button>
</StackPanel>
</Grid>
</ScrollViewer>
Also have a ItemsControl which is getting loaded like this and binding is working fine here
<ItemsControl Name="StoreListView" ItemsSource="{Binding StoreCollection}" Margin="5" VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingStackPanel.VirtualizationMode="Recycling" >
But ObservableCollection list binding is fine , but the label bindings are not working. How i can solve this?
How can i set binding on label based on properties of a class
I think WPF does not notice the change of the DbVersion property because you set it after calling InitializeComponent(). Either you implement it as a DependencyProperty, which automatically notices if it is changed (see: https://msdn.microsoft.com/en-us/library/ms750428(v=vs.110).aspx), or you use the INotifyPropertyChanged interface in your ManagePage class (see: https://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged(v=vs.110).aspx).
I have a ListView with textBox in one of the columns. User input on the textbox supposed to update the underlying data, that's what my requirement is, but it's not happening. I tried a work around as shown all the way below, it seems to work but I am guessing that the binding itself should take care of it without the work around.
XAML:
<ListView x:Name="listView" Grid.Row="1" ItemsSource="{Binding}" SelectionMode="Multiple">
<ListView.ItemTemplate>
<DataTemplate>
<Border Background="{Binding BackGround}">
<Grid x:Name="row">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock x:Name="tblDescription"
Grid.Row="0"
Grid.Column="0"
Margin="1"
TextWrapping="Wrap"
Text="{Binding Description}"
FontSize="{StaticResource TextStyleMediumFontSize}"
Foreground="Black"/>
<TextBlock x:Name="tblItemNumber"
Grid.Row="0"
Grid.Column="1"
Margin="1"
Text="{Binding ItemNumber}"
FontSize="{StaticResource TextStyleMediumFontSize}"
FontStyle="Italic"
Foreground="Gray"/>
<TextBox x:Name="tbQuantity"
Grid.Row="1"
Grid.Column="1"
Margin="1"
Text="{Binding Quantity}"
IsEnabled="{Binding IsEnabled}"
FontSize="{StaticResource TextStyleLargeFontSize}"
BorderBrush="DarkGray"
Foreground="Black"
InputScope="Number"
Tag="{Binding RowNumber}"
TextChanged="tbQuantity_TextChanged"
>
<TextBox.Header>Quantity</TextBox.Header>
</TextBox>
</Grid>
</Border>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
DataRow class:
public class DataRowBase : INotifyPropertyChanged
{
#region Events
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
#region Properties
public int RowNumber { get; set; }
public string ItemNumber { get; set; }
public string Description { get; set; }
private string _Quantity;
public string Quantity
{
get { return _Quantity; }
set {
_Quantity = value;
RaisePropertyChanged("Quantity");
}
}
#endregion
}
Work Around:
private void tbQuantity_TextChanged(object sender, TextChangedEventArgs e)
{
TextBox tb = (TextBox)sender;
int rownumber = tb.Tag.ToString().ToInt();
UpdateQuantity(rownumber, value: tb.Text);
}
private void UpdateQuantity(int rownumber, string value)
{
try
{
DataRow datarow = OriginalSource.Where(o => o.RowNumber == rownumber).FirstOrDefault();
if (datarow != null)
{
datarow.Quantity = value;
}
}
catch (Exception ex)
{
}
}
The default Binding is OneWay, for a TwoWay you will have to declare it, for example:
Text="{Binding ItemNumber, Mode=TwoWay}"