I have created a view model which has a single property for a student model, that I am then binding to a control in my XAML. But nothing is appearing when I execute the application.
I am setting data context in my app.xaml.cs as follows:
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
Registrationformusinemvvm.MainWindow window = new MainWindow();
VMUser VM = new VMUser();
window.DataContext = VM;
window.Show();
}
Why is the binding not working?
This is my view model:
public class VMUser:BaseClass
{
private student _currentStudent;
public student CurrentStudent
{
get { return _currentStudent; }
set {
_currentStudent = value;
OnPropertyChanged("CurrentStudent");
}
}
}
My Student model class:
public class student:BaseClass
{
private string name="sumit";
public string Name
{
get { return name; }
set { name = value; OnPropertyChanged("Name"); }
}
private int rollNum;
public int RollNum
{
get { return rollNum; }
set { rollNum = value;OnPropertyChanged("RollNum"); }
}
private int phNum;
public int PhNum
{
get { return phNum; }
set { phNum = value;OnPropertyChanged("PhNum"); }
}
private string sub;
public string Sub
{
get { return sub; }
set { sub = value;OnPropertyChanged("Sub"); }
}
}
My XAML:
<Window x:Class="Registrationformusinemvvm.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:Registrationformusinemvvm"
xmlns:vm="clr-namespace:Registrationformusinemvvm.ViewModel"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<!--<Window.DataContext>
<vm:VMUser/>
</Window.DataContext>-->
<Window.Resources>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition Height="50"/>
<RowDefinition Height="50"/>
<RowDefinition Height="50"/>
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="Name" Grid.Column="0" Grid.Row="0" FontSize="14"
FontWeight="Bold" VerticalAlignment="Center"
HorizontalAlignment="Center"/>
<TextBlock Text="Roll Number" Grid.Column="0" Grid.Row="1" FontSize="14"
FontWeight="Bold" VerticalAlignment="Center"
HorizontalAlignment="Center"/>
<TextBlock Text="Subject" Grid.Column="0" Grid.Row="2" FontSize="14"
FontWeight="Bold" VerticalAlignment="Center"
HorizontalAlignment="Center"/>
<TextBlock Text="Phone Number" Grid.Column="0" Grid.Row="3"
FontSize="14" FontWeight="Bold" VerticalAlignment="Center"
HorizontalAlignment="Center"/>
<TextBox Name="tbName" Text="{Binding CurrentStudent.Name,Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}" Grid.Column="1" Grid.Row="0"
Width="120" Height="30" HorizontalAlignment="Center"
VerticalAlignment="Center"/>
<TextBox Name="tbRollnum" Text="{Binding CurrentStudent.RollNum}"
Grid.Column="1" Grid.Row="1" Width="120" Height="30"
HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBox Name="tbSub" Text="{Binding CurrentStudent.Sub}"
Grid.Column="1" Grid.Row="2" Width="120" Height="30"
HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBox Name="tbPh" Text="{Binding CurrentStudent.PhNum}"
Grid.Column="1" Grid.Row="3" Width="120" Height="30"
HorizontalAlignment="Center" VerticalAlignment="Center"/>
<Button Name="tbSubmit" Content="Submit" Grid.ColumnSpan="3"
Grid.Row="4" Height="30" Width="100" HorizontalAlignment="Center"/>
</Grid>
</Window>
My guess is that your binding isn't working because your _currentStudent is null by default. Initialize your _currentStudent if null.
public student CurrentStudent
{
get { return _currentStudent = (_currentStudent ?? new student()); }
set
{
_currentStudent = value; OnPropertyChanged("CurrentStudent");
}
}
You need to add OnPropertyChanged in your model class.
void OnPropertyChanged(string prop)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(prop));
}
public event PropertyChangedEventHandler PropertyChanged;
As per your above code you cant assigned the value to CurrentStudent Property so
can you please check do you have the value to CurrentStudent property.
Thank you for your question
Remove StartupUri="YourXamlFile.xaml" from App.Xaml
Related
I need to change the color of a rectangle in a GridView when the item is selected.
Unselected item
Selected item
My Main Page in XAML.
<Page
x:Class="GridViewWithSelectedItem.Views.MainPage"
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:views="using:GridViewWithSelectedItem.Views"
Style="{StaticResource PageStyle}"
mc:Ignorable="d">
<Page.Resources>
<DataTemplate x:Key="TileTemplate" x:DataType="views:Article">
<Border BorderThickness="2,2,2,2" BorderBrush="#FF868484" Margin="3,3,3,3" HorizontalAlignment="Stretch" MaxWidth="600" MinWidth="525">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="60"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Rectangle Fill="Black" Grid.RowSpan="3"/>
<StackPanel Orientation="Horizontal" Grid.Row="0" Grid.Column="1">
<TextBlock FontSize="20" Margin="0,0,5,0" TextWrapping="Wrap" Foreground="DarkBlue" FontWeight="Bold" Text="{x:Bind Number}"/>
<TextBlock FontSize="20" TextWrapping="Wrap" Foreground="DarkBlue" Text="{x:Bind Title}" FontWeight="Bold"/>
</StackPanel>
<TextBlock Grid.Row="1" Grid.Column="1" FontSize="20" Text="{x:Bind Description}" TextWrapping="WrapWholeWords"/>
<StackPanel Background="LightBlue" Padding="5,0,0,0" Grid.Row="2" Grid.Column="1">
<StackPanel Orientation="Horizontal">
<TextBlock FontSize="20" Margin="0,0,5,0" TextWrapping="Wrap">Date :</TextBlock>
<TextBlock Foreground="Red" FontSize="20" TextWrapping="Wrap" Text="{x:Bind Date}" FontWeight="Bold"/>
</StackPanel>
</StackPanel>
</Grid>
</Border>
</DataTemplate>
</Page.Resources>
<Grid x:Name="ContentArea" Margin="{StaticResource MediumLeftRightMargin}">
<Grid Background="White" VerticalAlignment="Top" HorizontalAlignment="Stretch" Margin="0,25,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="600"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="60"/>
<RowDefinition Height="800"/>
</Grid.RowDefinitions>
<TextBlock Text="The Guardian" FontSize="35" FontWeight="Bold" Grid.ColumnSpan="2" HorizontalAlignment="Center"/>
<GridView
BorderThickness="2,2,0,2" BorderBrush="#FF868484"
MinWidth="600"
Grid.Column="0"
Grid.Row="1"
Padding="5,5,5,5"
HorizontalAlignment="Center"
CanDragItems="False"
IsItemClickEnabled="true"
IsTapEnabled="False"
IsSwipeEnabled="False"
ItemsSource="{x:Bind Articles}"
ItemTemplate="{StaticResource TileTemplate}"
SelectedItem="{x:Bind Mode=TwoWay, Path=SelectedArticle}"
/>
<RelativePanel Grid.Row="1" Grid.Column="1" Background="WhiteSmoke" BorderThickness="2" BorderBrush="#FF868484" Padding="10">
<Grid RelativePanel.AlignLeftWithPanel="True" RelativePanel.AlignRightWithPanel="True">
<Grid VerticalAlignment="Top">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" Grid.Row="0">
<TextBlock FontSize="20" Margin="0,0,5,0" TextWrapping="Wrap" Foreground="DarkBlue" FontWeight="Bold" Text="{x:Bind Path=SelectedArticle.Number, Mode=OneWay}"/>
<TextBlock FontSize="20" TextWrapping="Wrap" Foreground="DarkBlue" Text="{x:Bind Path=SelectedArticle.Title, Mode=OneWay}" FontWeight="Bold"/>
</StackPanel>
<TextBlock Grid.Row="1" FontSize="20" Text="{x:Bind Path=SelectedArticle.Description, Mode=OneWay}" TextWrapping="WrapWholeWords"/>
</Grid>
</Grid>
<RelativePanel Background="LightBlue" Padding="5,0,0,0" RelativePanel.AlignBottomWithPanel="True" RelativePanel.AlignLeftWithPanel="True" RelativePanel.AlignRightWithPanel="True">
<StackPanel Orientation="Horizontal">
<TextBlock FontSize="20" Margin="0,0,5,0" TextWrapping="Wrap">Date :</TextBlock>
<TextBlock Foreground="Red" FontSize="20" TextWrapping="Wrap" Text="{x:Bind Path=SelectedArticle.Date, Mode=OneWay}" FontWeight="Bold"/>
</StackPanel>
</RelativePanel>
</RelativePanel>
</Grid>
</Grid>
</Page>
And the class of my XAML Page.
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using Windows.UI.Xaml.Controls;
namespace GridViewWithSelectedItem.Views
{
public sealed partial class MainPage : Page, INotifyPropertyChanged
{
public ObservableCollection<Article> Articles;
private Article _selectedArticle;
public Article SelectedArticle
{
get { return _selectedArticle; }
set { Set(ref _selectedArticle, value); }
}
public MainPage()
{
InitializeComponent();
Articles = new ObservableCollection<Article>();
Articles.Add(new Article(0, "Uighurs", "Being young' leads to detention in China's Xinjiang region", DateTime.Parse("09/12/2020")));
Articles.Add(new Article(1, "Brexit", "Chances of Brexit deal hang on Boris Johnson and Ursula von der Leyen dinner", DateTime.Parse("09/12/2020")));
Articles.Add(new Article(2, "Environment", "Secretive ‘gold rush’ for deep-sea mining dominated by handful of firms", DateTime.Parse("09/12/2020")));
Articles.Add(new Article(3, "Juukan Gerge induiry", "Juukan Gorge inquiry: Rio Tinto's decision to blow up Indigenous rock shelters 'inexcusable'", DateTime.Parse("09/12/2020")));
Articles.Add(new Article(4, "Australia", "British journalist uncovered Australian woman's alleged plan to kill parents on dark web, police say", DateTime.Parse("09/12/2020")));
Articles.Add(new Article(5, "Coronavirus", "Nine out of 10 in poor nations to miss out on inoculation as west buys up Covid vaccines", DateTime.Parse("09/12/2020")));
}
public event PropertyChangedEventHandler PropertyChanged;
private void Set<T>(ref T storage, T value, [CallerMemberName]string propertyName = null)
{
if (Equals(storage, value))
{
return;
}
storage = value;
OnPropertyChanged(propertyName);
}
private void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public class Article
{
public int Number { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public DateTime Date { get; set; }
public Article(int number, string title, string description, DateTime date)
{
Number = number;
Title = title;
Description = description;
Date = Date;
}
}
}
I see AutomationProperty.name can help me but i don't understand how to use it.
I found a way to change the color of a selected item in my class but i need to recreate the collection and i cost lot of resources. I think its possible to make it in XAML code.
Edit: I made a simple exemple of my code.
OneDrive link
You could add a Brush property into the Article class, and bind the Brush property to Rectangle.Fill property of your DataTemplate to change the color when an item of GridView control is selected.
Please check the following code:
In DataTemplate of your xaml file:
<Rectangle x:Name="rectangle" Fill="{x:Bind Brush}" Grid.RowSpan="3"/>
……
<GridView …… SelectionChanged="GridView_SelectionChanged" />
In code-behind:
public class Article
{
……
public SolidColorBrush Brush { get; set; }
public Article(int number, string title, string description, DateTime date)
{
……
Brush = new SolidColorBrush(Colors.Black);
}
}
Add a _preSelectedArticle property to save the previous item in MainPage class:
private Article _preSelectedArticle;
Change the value of Brush property of selected item and previous selected item:
private void GridView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if(_preSelectedArticle==null)
{
SelectedArticle.Brush.Color = Colors.Green;
_preSelectedArticle = SelectedArticle;
}
if (_preSelectedArticle!=null&&_preSelectedArticle!= SelectedArticle)
{
_preSelectedArticle.Brush.Color = Colors.Black;
SelectedArticle.Brush.Color = Colors.Green;
_preSelectedArticle = SelectedArticle;
}
}
I have a counter which increments depending on a foreach Loop from:
public partial class UserControlCounter : UserControl, INotifyPropertyChanged
{
private int _scanStatusCounter;
public int ScanStatusCounter
{
get { return _scanStatusCounter; }
set { _scanStatusCounter = value; NotifyPropertyChanged(); }
}
public UserControlCounter()
{
InitializeComponent();
DataContext = this;
}
private async void Button_Click(object sender, RoutedEventArgs e)
{
await Task.Run(getAll);
scanStatus.Text = "Persons " + ScanStatusCounter.ToString();
}
private async void getAll()
{
//grab data and iterate it
string[] string_array = new string[] { "a", "b", "c", "d", "e" }; // type = System.String[]
foreach (var i in string_array)
{
ScanStatusCounter++;
await Task.Delay(100);
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
and the Xaml:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="60"/>
</Grid.RowDefinitions>
<ListBox Grid.Row="0" Grid.Column="0" Name="myListBox" Height="40" ></ListBox>
<TextBlock Grid.Row="0" Grid.Column="1" Name="scanStatus" Height="40" Text="{Binding Path=ScanStatusCounter, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></TextBlock>
<Button Grid.Row="0" Grid.Column="2" Click="Button_Click" Height="40">Click Me</Button>
</Grid>
That works fine and increments "live", but my problem is that I need to get that now running inside a more complex Data Template.
I've tried to inject the Counter onClick with:
private async void Button_Click(object sender, RoutedEventArgs e)
{
var btn = sender as Button;
var contentPresenter = (btn.TemplatedParent as ContentPresenter);
var ppStatusCounter = contentPresenter.ContentTemplate.FindName("scanStatus", contentPresenter) as TextBlock;
ppStatusCounter.Text = "Entrys found: " + ScanStatusCounter.ToString();
}
But then I get the Value only onClick not like a live incrementing Counter, that's my Data Template:
<UserControl.Resources>
<c1:NameList x:Key="NameListData"/>
<DataTemplate x:Key="NameItemTemplate">
<Grid Margin="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="40"></RowDefinition>
<RowDefinition Height="40"></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="Domaine"/>
<TextBox Grid.Row="1" Grid.Column="0" x:Name="txtDomainName" Text="{Binding Path=DomaineName}" Margin="0,0,5,0"></TextBox>
<Button Grid.Row="1" Grid.Column="1" Width="100" Height="30" Margin="5,5,5,5" x:Name="btnNames" Click="Button_Click" Content="Start Scan" />
<Grid Grid.Column="2" Grid.Row="1" Height="20">
<ProgressBar x:Name="pbStatus" Height="20" Width="100" Minimum="0" Maximum="100" Visibility="Hidden"/>
<TextBlock x:Name="pbStatusText" HorizontalAlignment="Center" VerticalAlignment="Center" Text="Scanning" Visibility="Hidden"/>
</Grid>
<TextBlock Grid.Column="3" Grid.Row="1" Name="scanStatus" Text="{Binding Path=ScanStatusCounter, UpdateSourceTrigger=PropertyChanged}"/>
</Grid>
</DataTemplate>
</UserControl.Resources>
<Grid>
<StackPanel Orientation="Horizontal" VerticalAlignment="top">
<StackPanel Orientation="Horizontal" Margin="0,20,0,0">
<ListBox x:Name="lstDomainNames"
Margin="5,5,5,5"
ItemsSource="{Binding Source={StaticResource NameListData}}"
ItemTemplate="{StaticResource NameItemTemplate}"
IsSynchronizedWithCurrentItem="True"/>
</StackPanel>
</StackPanel>
</Grid>
that's my Data Source Class, not much there:
public partial class NameList : ObservableCollection<SetCredentials>
{
private static Logger logger = LogManager.GetCurrentClassLogger();
public NameList() : base()
{
using var forest = Forest.GetCurrentForest();
Forest currentForest = Forest.GetCurrentForest();
DomainCollection domains = currentForest.Domains;
foreach (Domain objDomain in domains)
{
Add(new SetCredentials(objDomain.ToString()));
}
}
}
public class SetCredentials
{
private string domainName;
public SetCredentials(string domain)
{
this.domainName = domain;
}
public string DomaineName
{
get { return domainName; }
set { domainName = value; }
}
}
Do I have to add a second Data Binding source to my ItemSource or do I need another approach for this, for example in my TextBox Binding?
What I want to do is to be able to access an object's properties through a bound textblock that is found in a viewModel class. So say I want to access the OrderID of the Orders class in a bound textblock that is stored in a viewModel class.
What I have for that is:
<textblock text="{Binding Path=Order.OrderID}"/>
This is connected to the order's orderID as when I change the OrderID in the ViewModel class the change is reflected in the textblock. The problem occurs when I try to load the OrderID from another class.
The Other class:
public class ModifyOrder
{
private ViewModel boundData;
public ModifyOrder()
{
boundData = new ViewModel();
}
public void ChangeOrderID()
{
boundData.Order.OrderID = 10;
}
}
The changes here don't get transfered to the static _Order in the ViewModel class.
This is the viewModel class:
public class ViewModel : INotifyPropertyChanged
{
private Orders _Order;
public Orders Order
{
get { return _Order; }
set
{
if (_Order != value)
{
_Order = value;
}
}
}
public ViewModel()
{
Order = new Orders();
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
I have the ViewModel class loaded into the UI's DataContext and my other bound variables in the ViewModel class work fine but for some reason either the bound textblock isn't accessing the Order.OrderID (Which I don't think is the problem since I can modify the Order.OrderID in the ViewModel class and the changes are reflected) OR the class that's modifying my Order isn't able to modify the OrderID.
I've already tried to load a new Order class with the new OrderID and then try to load the ViewModel's _Order with the ModifyOrder's new Order but that hasn't worked out either.
This is the Orders class:
public class Orders : INotifyPropertyChanged
{
private int _OrderID;
public int OrderID
{
get { return _OrderID; }
set
{
if(_OrderID != value)
{
_OrderID = Value
OnPropertyChanged(nameof(OrderID));
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
<Page x:Class="SPWally.FunctionalPages.LookupOrders"
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:SPWally.FunctionalPages"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
Title="LookupOrders">
<Grid Background="AliceBlue">
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition Height="30"/>
<RowDefinition Height="*"/>
<RowDefinition Height="20"/>
<RowDefinition Height="20"/>
<RowDefinition Height="20"/>
<RowDefinition Height="20"/>
<RowDefinition Height="20"/>
<RowDefinition Height="20"/>
<RowDefinition Height="*"/>
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="30" Text="Search For Order" />
<TextBlock Grid.Row="1" Grid.Column="0" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="0,0,335,0" Text="OrderID: " />
<TextBox Grid.Row="1" Grid.Column="0" HorizontalAlignment="Right" VerticalAlignment="Center" Width="300" Margin="0,0,20,0" Text="{Binding Path=OrderIDSearch, Mode=OneWayToSource, UpdateSourceTrigger=PropertyChanged}" />
<Button Grid.Row="1" Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Center" Width="40" Height="20" Margin="10,0,0,0" Content="Find" Click="Find_Click" />
<Button Grid.Row="1" Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Center" Width="50" Height="20" Margin="70,0,0,0" Content="Refund" Click="Refund_Click" />
<TextBlock Grid.Row="3" Grid.Column="0" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="0,0,100,0" Text="OrderID:"/>
<TextBlock Grid.Row="4" Grid.Column="0" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="0,0,100,0" Text="Customer:"/>
<TextBlock Grid.Row="5" Grid.Column="0" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="0,0,100,0" Text="Product:"/>
<TextBlock Grid.Row="6" Grid.Column="0" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="0,0,100,0" Text="Branch:"/>
<TextBlock Grid.Row="7" Grid.Column="0" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="0,0,100,0" Text="Sales Price:"/>
<TextBlock Grid.Row="8" Grid.Column="0" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="0,0,100,0" Text="Quantity:"/>
<TextBlock Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" HorizontalAlignment="Center" VerticalAlignment="Center" Width="200" Margin="30,0,0,0" Text="{Binding Path=Order.OrderID, Mode=TwoWay}"/>
<TextBlock Grid.Row="4" Grid.Column="0" Grid.ColumnSpan="2" HorizontalAlignment="Center" VerticalAlignment="Center" Width="200" Margin="30,0,0,0" Text="{Binding Path=Order.Customer.FullName, Mode=TwoWay}"/>
<TextBlock Grid.Row="5" Grid.Column="0" Grid.ColumnSpan="2" HorizontalAlignment="Center" VerticalAlignment="Center" Width="200" Margin="30,0,0,0" Text="{Binding Path=Order.Product.ProductName, Mode=TwoWay}"/>
<TextBlock Grid.Row="6" Grid.Column="0" Grid.ColumnSpan="2" HorizontalAlignment="Center" VerticalAlignment="Center" Width="200" Margin="30,0,0,0" Text="{Binding Path=Order.Branch.BranchName, Mode=TwoWay}"/>
<TextBlock Grid.Row="7" Grid.Column="0" Grid.ColumnSpan="2" HorizontalAlignment="Center" VerticalAlignment="Center" Width="200" Margin="30,0,0,0" Text="{Binding Path=Order.SalesPrice, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<TextBlock Grid.Row="8" Grid.Column="0" Grid.ColumnSpan="2" HorizontalAlignment="Center" VerticalAlignment="Center" Width="200" Margin="30,0,0,0" Text="{Binding Path=Order.Stocks, Mode=TwoWay}"/>
<Button Grid.Row="10" Grid.Column="0" Grid.ColumnSpan="2" HorizontalAlignment="Center" VerticalAlignment="Center" Width="60" Height="25" Content="Cancel" Command="{x:Static NavigationCommands.BrowseBack}" />
</Grid>
</Page>
Keep in mind that I've literally learned everything I know about data binding in the last 48 hours so bear with me here.
Any kind of help at all is very much appreciated. Thank!
You need to implement INotifyPropertyChanged in Orders class.
You need to Invoke OnPropertyChanged() inside all setters.
Where your view model is getting instantiated ? I guess since you are recreating your viewmodel instance in ModifyOrder class
boundData = new ViewModel();
binding is lost and may be because of that its not showing up .
...Yeah, so. It was the
public ViewModel()
{
Order = new Order();
}
that was wiping clean the private static Orders _Order in the ViewModel class every time it was instantiated so I changed it to
public ViewModel()
{
if (_Order == null)
{
Order = new Order();
}
}
and that fixed the problem...
Thanks to everyone that helped me out with this! I learned a lot from you all!
I'm going to go cry myself to sleep now <3
I'm currently trying to bind my list to a list that is in another object from another list. But in the second listbox the Items just doesn't appear.
XAML
<Window x:Class="Managing_program.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:Managing_program"
mc:Ignorable="d"
Title="Dashboard" Height="416.701" Width="867.828">
<Grid>
<TabControl Margin="0,26,0,0">
<TabItem Header="Tables">
<Grid Background="White" Margin="0,0,-2,0">
<Button Content="Add" Margin="10,0,0,10" Height="20" VerticalAlignment="Bottom" HorizontalAlignment="Left" Width="75" Command="{Binding AddTableCommand}"/>
<Button Content="Remove" Margin="90,0,0,10" HorizontalAlignment="Left" Width="75" Height="20" VerticalAlignment="Bottom" Command="{Binding RemoveTableCommand}"/>
<GroupBox Header="Fields" HorizontalAlignment="Left" Margin="204,0,0,35" Width="192" FontWeight="Bold">
<Grid ShowGridLines="False">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="30"/>
</Grid.RowDefinitions>
<ListBox Grid.Row="0" BorderThickness="2" ItemsSource="{Binding SelectedTable.Fields}" SelectedItem="{Binding SelectedField}" Margin="0 4" FontWeight="Normal">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<Label Content="test"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<TextBox Grid.Row="1" Margin="2" Text="{Binding FieldNameToAdd, Mode=TwoWay , UpdateSourceTrigger=PropertyChanged}"/>
</Grid>
</GroupBox>
<GroupBox Header="Tables" HorizontalAlignment="Left" Width="199" Margin="0,0,0,35" FontWeight="Bold">
<Grid ShowGridLines="False">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="30"/>
</Grid.RowDefinitions>
<TextBox x:Name="tbAddTable" Grid.Row="1" Margin="2" Text="{Binding Path=TableNameToAdd, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
<ListBox Grid.Row="0" ItemsSource="{Binding Tables}" SelectedItem="{Binding SelectedTable}" BorderThickness="2" Margin="0 4" FontWeight="Normal">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<Label Content="{Binding Name}"/>
<Label Content= "{Binding Fields.Count, StringFormat='Fields: {0}'}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</GroupBox>
<Button Content="Add" Margin="207,0,0,10" Height="20" VerticalAlignment="Bottom" HorizontalAlignment="Left" Width="75" Command="{Binding AddFieldCommand}"/>
<Button Content="Remove" Margin="287,0,0,10" HorizontalAlignment="Left" Width="75" Height="20" VerticalAlignment="Bottom" Command="{Binding RemoveFieldCommand}"/>
<GroupBox Header="Field properties" Margin="401,0,10,35" FontWeight="Bold">
<Grid Margin="10,10,-2,5" ShowGridLines="True" DataContext="{Binding SelectedField}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="28"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="200"/>
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Content="Name:"/>
<Label Grid.Row="1" Grid.Column="0" Content="Label:"/>
<Label Grid.Row="2" Grid.Column="0" Content="Type:"/>
<Label Grid.Row="3" Grid.Column="0" Content="Reference table:"/>
<Label Grid.Row="4" Grid.Column="0" Content="Visible:"/>
<Label Grid.Row="0" Grid.Column="1" Content="{Binding Name}" Margin="10,0,0,0"/>
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Label}" Margin="5,2,0,2"/>
<ComboBox Grid.Column="1" Margin="5,5,0,5" Grid.Row="2" BorderBrush="White" RenderTransformOrigin="1.029,0.62">
</ComboBox>
<ComboBox Grid.Column="1" Margin="5,5,-0,121" Grid.Row="3" BorderBrush="White" RenderTransformOrigin="1.029,0.62">
</ComboBox>
</Grid>
</GroupBox>
</Grid>
</TabItem>
<TabItem Header="TabItem">
</TabItem>
</TabControl>
</Grid>
</Window>
MainViewModel:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
namespace Managing_program.model
{
class MainWindowViewModel: ViewModelBase
{
public MainWindowViewModel()
{
// registering all commands
Tables = new ObservableCollection<Table>();
AddTableCommand = new DelegateCommand(ExecuteAddTableCommand, CanExecuteAddTableCommand);
RemoveTableCommand = new DelegateCommand(ExecuteRemoveTableCommand, CanExecuteRemoveTableCommand);
AddFieldCommand = new DelegateCommand(ExecuteAddFieldCommand, CanExecuteAddFieldCommand);
}
String _fieldNameToAdd = String.Empty;
public String FieldNameToAdd {
get { return _fieldNameToAdd; }
set {
_fieldNameToAdd = value;
OnPropertyChanged("FieldNameToAdd");
}
}
String _tableNameToAdd = string.Empty;
public String TableNameToAdd {
get {return _tableNameToAdd;}
set {
_tableNameToAdd = value;
OnPropertyChanged("TableNameToAdd");
}
}
#region allCommands:
// Add Table Command
public ICommand AddTableCommand { get; set; }
private void ExecuteAddTableCommand(object parameter)
{
Tables.Add(new Table(TableNameToAdd));
TableNameToAdd = String.Empty;
}
private bool CanExecuteAddTableCommand(object paramater)
{
if (TableNameToAdd.Length < 1)
return false;
if (TableNameToAdd.Contains(" "))
return false;
foreach (Table table in Tables)
{
if (table.Name.ToLower() == TableNameToAdd)
return false;
}
return true;
}
// Remove Table Command
public ICommand RemoveTableCommand { get; set; }
private void ExecuteRemoveTableCommand(object paramater){
Tables.Remove(SelectedTable);
}
private bool CanExecuteRemoveTableCommand(object parameter)
{
return SelectedTable != null;
}
// AddFieldCommand
public ICommand AddFieldCommand { get; set; }
private void ExecuteAddFieldCommand(object parameter)
{
SelectedTable.Fields.Add(new Field("test"));
}
private bool CanExecuteAddFieldCommand(object parameter)
{
if (SelectedTable == null)
return false;
if (FieldNameToAdd.Length < 1)
return false;
if (FieldNameToAdd.Contains(" "))
return false;
foreach (Field field in SelectedTable.Fields)
{
if (field.Name.ToLower() == FieldNameToAdd.ToLower())
return false;
}
return true;
}
#endregion
public ObservableCollection<Table> Tables { get; private set; }
public Table SelectedTable { get; set; }
public Field SelectedField { get; set; }
}
}
Table class:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Managing_program.model
{
class Table
{
public Table(String name)
{
Name = name;
Fields = new ObservableCollection<Field>();
}
public String Name { get; private set; }
public ObservableCollection<Field> Fields { get; private set; }
}
}
The second listbox just doesn't update. Please help!
Okay I found the problem! I had to implement OnPropertyChanged() in the SelectedTable property. It start to work right away after that!
I have class
public class Clip
{
public string ID { get; set; }
public string Name { get; set; }
public int? Duration { get; set; }
}
And ObservableCollection
public ObservableCollection<Clip> _clipsFound;
public ObservableCollection<Clip> collection
{
get { return _clipsFound; }
set
{
_clipsFound = value;
OnPropertyChanged();
}
}
OnPropertyChanged() is invoked when I do
_clipsFound = collection
I want binding data from collection to ListBox with three columns: ID, Name, Duration
Initialize
ID = id;
collection = new ObservableCollection<Clip>();
_clipsFound = collection;
_clipsFound.Clear();
ICollection<Clip> ClipF = await Service.GetClips(ID);
ICollection<Clip> Clipcol = ClipF;
collection = new ObservableCollection<Clip>(Clipcol);
I try do this, but it doesn't work
<ListBox Grid.Row="2" ItemsSource="{Binding collection}" BorderBrush="Transparent" >
<ListBox.ItemTemplate>
<DataTemplate DataType="ui:Clip">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0"
Text="{Binding Title}"
VerticalAlignment="Center"
HorizontalAlignment="Left"
TextTrimming="CharacterEllipsis"
Foreground="#FF4F4F4F"
FontSize="12"
Margin="55 0 0 0"/>
<TextBlock Grid.Column="1"
Margin="0 0 45 0"
Text="{Binding Duration}"
VerticalAlignment="Center"
HorizontalAlignment="Right"
FontSize="11"
Foreground="#FF4F4F4F"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
What did I do wrong?
You cannot send data from viewmodel to view without setting DataContext. DataContext is like channel or bridge between ViewModel and View.
This code sets DataContext:
<Window.DataContext>
<vm:MainWindowViewModel />
</Window.DataContext>
Let's see work example:
Your ViewModel:
public class MainWindowViewModel
{
publicMainWindowViewModel
{
LoadData();
}
private void LoadData()
{
_clipsFound=new ObservableCollection<Clip>();
for(int startIndex=0; startIndex<10; startIndex++)
{
collection.Add(new Clip(){ID=startIndex, Name="Bob", Duration=startIndex++});
}
}
public ObservableCollection<Clip> _clipsFound;
public ObservableCollection<Clip> collection
{
get
{
return _clipsFound;
}
set
{
_clipsFound = value;
}
}
}
Your XAML:
<Window x:Class="DataGridSelectedItemsWpfApplication.MainWindow"
...The code omitted for the brevity...
xmlns:vm="clr-namespace:DataGridSelectedItemsWpfApplication.ViewModel"
Title="MainWindow" WindowStartupLocation="CenterScreen" Height="550" Width="525">
<Window.DataContext>
<vm:MainWindowViewModel />
</Window.DataContext>
<ListBox Grid.Row="2" ItemsSource="{Binding collection}" BorderBrush="Transparent" >
<ListBox.ItemTemplate>
<DataTemplate DataType="ui:Clip">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding ID}" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="11" Margin="2" Foreground="#FF4F4F4F"/>
<TextBlock Grid.Column="1" Margin="2" Text="{Binding Name}" VerticalAlignment="Center" HorizontalAlignment="Center" TextTrimming="CharacterEllipsis" Foreground="#FF4F4F4F" FontSize="12"/>
<TextBlock Grid.Column="2" Margin="2" Text="{Binding Duration}" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="11" Foreground="#FF4F4F4F"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Window>
There are many ways to set DataContext.