I have created two WPF user controls having multiple textboxes, comboboxes and buttons. In the main wpf window, I have created a Canvas and a listbox with two listitems in it. My requirement is, if select the first listbox item, the first user control should get added to canvas. If I select the second listbox item, the previously added user control should get hide, and second one should get added/showed. Can anyone provide an expample for this code?
Below is code I have writtent.I have created two user controls.
UserControl1.xaml
<UserControl x:Class="UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="210" Height="210" x:Name="UCntl1">
<Grid>
<StackPanel>
<GroupBox Header="Text Boxes">
<StackPanel Orientation="Horizontal">
<StackPanel>
<Label Margin="4" Height="21">TextBox1</Label>
<Label Margin="4" Height="21">TextBox2</Label>
<Label Margin="4" Height="21">TextBox3</Label>
</StackPanel>
<StackPanel>
<TextBox Width="100" Height="21" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="4">0.1</TextBox>
<TextBox Width="100" Height="21" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="4">0.2</TextBox>
<TextBox Width="100" Height="21" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="4">0.3</TextBox>
</StackPanel>
</StackPanel>
</GroupBox>
<GroupBox Header="Conbo Boxes">
<StackPanel Orientation="Horizontal">
<StackPanel>
<Label Margin="4" Height="21">ComboBox1</Label>
<Label Margin="4" Height="21">ComboBox2</Label>
<Label Margin="4" Height="21">ComboBox3</Label>
</StackPanel>
<StackPanel>
<ComboBox Width="100" Height="21" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="4">
<ComboBoxItem>Item AAA</ComboBoxItem>
</ComboBox>
<ComboBox Width="100" Height="21" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="4">
<ComboBoxItem>Item BBB</ComboBoxItem>
</ComboBox>
<ComboBox Width="100" Height="21" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="4">
<ComboBoxItem>Item CCC</ComboBoxItem>
</ComboBox>
</StackPanel>
</StackPanel>
</GroupBox>
</StackPanel>
</Grid>
</UserControl>
UserControl2.xaml
<UserControl x:Class="UserControl2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="210" Height="210" x:Name="UCntl2">
<Grid>
<StackPanel>
<GroupBox Header="Conbo Boxes">
<StackPanel Orientation="Horizontal">
<StackPanel>
<Label Margin="4" Height="21">ComboBox1</Label>
<Label Margin="4" Height="21">ComboBox2</Label>
<Label Margin="4" Height="21">ComboBox3</Label>
</StackPanel>
<StackPanel>
<ComboBox Width="100" Height="21" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="4"></ComboBox>
<ComboBox Width="100" Height="21" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="4"></ComboBox>
<ComboBox Width="100" Height="21" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="4"></ComboBox>
</StackPanel>
</StackPanel>
</GroupBox>
<GroupBox Header="Text Boxes">
<StackPanel Orientation="Horizontal">
<StackPanel>
<Label Margin="4" Height="21">TextBox1</Label>
<Label Margin="4" Height="21">TextBox2</Label>
<Label Margin="4" Height="21">TextBox3</Label>
</StackPanel>
<StackPanel>
<TextBox Width="100" Height="21" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="4"></TextBox>
<TextBox Width="100" Height="21" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="4"></TextBox>
<TextBox Width="100" Height="21" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="4"></TextBox>
</StackPanel>
</StackPanel>
</GroupBox>
</StackPanel>
</Grid>
Window1.xaml
<Window x:Class="Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="Auto" Width="Auto">
<Grid>
<StackPanel Orientation="Horizontal">
<Grid Margin="0,0,0,0" Width="Auto" Height="Auto" VerticalAlignment="Top">
<ListBox Margin="0,0,0,0" HorizontalAlignment="Left" Width="Auto" Height="Auto" VerticalAlignment="Top" BorderBrush="White">
<ListBoxItem Name="LstItem1" Selected="LstItem1_Selected">User Control 1</ListBoxItem>
<ListBoxItem Name="LstItem2" Selected="LstItem2_Selected">User Control 2</ListBoxItem>
</ListBox>
</Grid>
<Grid Width="10" Background="LightGray"></Grid>
<Grid Margin="0,0,0,0">
<Canvas Name="Canvas1" Width="210" Height="210" VerticalAlignment="Top">
</Canvas>
</Grid>
</StackPanel>
</Grid>
Widow1.xaml.vb
Class Window1
Private Sub LstItem1_Selected(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
Canvas1.Children.Clear()
Canvas1.Children.Add(New UserControl1)
End Sub
Private Sub LstItem2_Selected(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
Canvas1.Children.Clear()
Canvas1.Children.Add(New UserControl2)
End Sub
End Class
Problem
I have added the user control after removing the previous controls in the canvas. Because of this the selected values in the list boxes in UserControls are getting cleared while re-adding the control to the canvas. Is there any method to hide the usercontrols on the canvas, instead of removing the controls from canvas.
This should get you started. It's not exactly how I'd do it in a real project, but close enough. I wish there was an easy way to attach projects to answers on this site.
The end result looks like this:
App.xaml:
<Application x:Class="SO9735486.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:SO9735486.ViewModels"
xmlns:v="clr-namespace:SO9735486.Views"
StartupUri="MainWindow.xaml">
<Application.Resources>
<DataTemplate DataType="{x:Type vm:MainViewModel}">
<v:MainView/>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:FirstContentViewModel}">
<v:FirstContentView/>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:SecondContentViewModel}">
<v:SecondContentView/>
</DataTemplate>
</Application.Resources>
</Application>
MainWindow.xaml:
<Window x:Class="SO9735486.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow">
</Window>
MainWindow.xaml.cs:
namespace SO9735486
{
using System.Windows;
using SO9735486.ViewModels;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.Content = new MainViewModel();
}
}
}
ViewModel.cs:
namespace SO9735486.ViewModels
{
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Threading;
// http://kentb.blogspot.com/2009/04/mvvm-infrastructure-viewmodel.html
public abstract class ViewModel : INotifyPropertyChanged
{
private readonly Dispatcher _dispatcher;
protected ViewModel()
{
if (Application.Current != null)
{
_dispatcher = Application.Current.Dispatcher;
}
else
{
//this is useful for unit tests where there is no application running
_dispatcher = Dispatcher.CurrentDispatcher;
}
}
[field: NonSerialized]
public event PropertyChangedEventHandler PropertyChanged;
protected Dispatcher Dispatcher
{
get { return _dispatcher; }
}
protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
{
var handler = this.PropertyChanged;
if (handler != null)
{
handler(this, e);
}
}
protected void OnPropertyChanged(string propertyName)
{
OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
}
}
}
ContentViewModel.cs:
namespace SO9735486.ViewModels
{
public abstract class ContentViewModel : ViewModel
{
private readonly string displayName;
protected ContentViewModel(string displayName)
{
this.displayName = displayName;
}
public string DisplayName
{
get { return this.displayName; }
}
}
}
FirstContentViewModel.cs:
namespace SO9735486.ViewModels
{
public sealed class FirstContentViewModel : ContentViewModel
{
private string name;
public FirstContentViewModel()
: base("First")
{
}
public string Name
{
get { return this.name; }
set
{
if (this.name != value)
{
this.name = value;
this.OnPropertyChanged("Name");
}
}
}
}
}
SecondContentViewModel.cs:
namespace SO9735486.ViewModels
{
public sealed class SecondContentViewModel : ContentViewModel
{
public SecondContentViewModel()
: base("Second")
{
}
}
}
MainViewModel.cs:
namespace SO9735486.ViewModels
{
using System.Collections.Generic;
using System.Linq;
public sealed class MainViewModel : ViewModel
{
private readonly ICollection<ContentViewModel> contentViewModels;
private ContentViewModel selectedContentViewModel;
public MainViewModel()
{
this.contentViewModels = new List<ContentViewModel>
{
new FirstContentViewModel(),
new SecondContentViewModel()
};
this.selectedContentViewModel = this.contentViewModels.First();
}
public ICollection<ContentViewModel> ContentViewModels
{
get { return this.contentViewModels; }
}
public ContentViewModel SelectedContentViewModel
{
get { return this.selectedContentViewModel; }
set
{
if (this.selectedContentViewModel != value)
{
this.selectedContentViewModel = value;
this.OnPropertyChanged("SelectedContentViewModel");
}
}
}
}
}
FirstContentView.xaml:
<UserControl x:Class="SO9735486.Views.FirstContentView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel>
<Label>First Content View</Label>
<TextBox Text="{Binding Name}"/>
</StackPanel>
</UserControl>
SecondContentView.xaml:
<UserControl x:Class="SO9735486.Views.SecondContentView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel>
<Label>Second content view</Label>
<Rectangle Fill="Blue" Width="100" Height="30"/>
</StackPanel>
</UserControl>
MainView.xaml:
<UserControl x:Class="SO9735486.Views.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<DockPanel>
<ComboBox DockPanel.Dock="Top" ItemsSource="{Binding ContentViewModels}" SelectedItem="{Binding SelectedContentViewModel}" DisplayMemberPath="DisplayName"/>
<ContentControl Content="{Binding SelectedContentViewModel}"/>
</DockPanel>
</UserControl>
Changes done for Windows1.xaml.vb only. The code bhind file should be as below. The answer for the problem is instead of callinf Canvas1.Clear(), set the visibilty of the added user controls to Windows.Visibility.Collapsed.
Window1.xaml.vb
Class Window1
Private U1 As Integer
Private U2 As Integer
Private Sub LstItem1_Selected(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
Canvas1.Children.Item(U1).Visibility = Windows.Visibility.Visible
Canvas1.Children.Item(U2).Visibility = Windows.Visibility.Collapsed
End Sub
Private Sub LstItem2_Selected(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
Canvas1.Children.Item(U2).Visibility = Windows.Visibility.Visible
Canvas1.Children.Item(U1).Visibility = Windows.Visibility.Collapsed
End Sub
Private Sub Window1_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded
U1 = Canvas1.Children.Add(New UserControl1)
U2 = Canvas1.Children.Add(New UserControl2)
Canvas1.Children.Item(U1).Visibility = Windows.Visibility.Collapsed
Canvas1.Children.Item(U2).Visibility = Windows.Visibility.Collapsed
End Sub
End Class
Related
I have a WPF XAML page, having 3 sections separated by DockPanels. One panel contains an INFRAGITICS XamDataGrid control to be bound with a collection.
I would like to bind XamDataGrid control using DataContext/DataSource property in pure MVVM way.
Also, would be delighted to understand if binding is done through dependency injection.
I have tried different approaches but didn't get success. I have pasted my code below for reference. Kindly help.
XAML Page:
<Window x:Class="UserInterface.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:UserInterface"
xmlns:igDP="clr-namespace:Infragistics.Windows.DataPresenter;assembly=InfragisticsWPF.DataPresenter"
xmlns:igEditors="clr-namespace:Infragistics.Windows.Editors;assembly=InfragisticsWPF.Editors"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:dc ="clr-namespace:UserInterface.ViewModel"
xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase"
mc:Ignorable="d"
Title="MainWindow">
<Window.Resources>
<dc:GraphicViewModel x:Key="dataContext"/>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height=".5*"/>
<RowDefinition Height=".5*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width=".5*"/>
<ColumnDefinition Width=".5*"/>
</Grid.ColumnDefinitions>
<DockPanel Grid.Column="0" Grid.Row="0">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
</Grid>
<!--<StackPanel Orientation="Vertical" DockPanel.Dock="Top">
<StackPanel Orientation="Horizontal" Margin="5" Grid.Row="0">
<DockPanel>
<TextBlock Text="*.cfg File" Grid.Column="0" DockPanel.Dock="Left"/>
<Button Content="Browse..." Grid.Column="2" DockPanel.Dock="Right"/>
<TextBox FontStyle="Italic" FontWeight="Light" Text="Browse *.cfg file..." Grid.Column="1" DockPanel.Dock="Right"/>
</DockPanel>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="5" Grid.Row="1">
<TextBlock Text="*.ps File " Grid.Column="0"/>
<TextBox FontStyle="Italic" FontWeight="Light" Text="Browse *.ps file..." Grid.Column="1"/>
<Button Content="Browse..." Grid.Column="2"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="5" Grid.Row="2">
<TextBlock Text="*.pic File " Grid.Column="0"/>
<TextBox FontStyle="Italic" FontWeight="Light" Text="Browse *.pic file..." Grid.Column="1"/>
<Button Content="Browse..." Grid.Column="2"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="5" Grid.Row="3">
<TextBlock Text="*.xlsx File" Grid.Column="0"/>
<TextBox FontStyle="Italic" FontWeight="Light" Text="Browse *.xlsx file..." Grid.Column="1"/>
<Button Content="Browse..." Grid.Column="2"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="5" Grid.Row="4">
<TextBlock Text="*.xlsx File"/>
<TextBox FontStyle="Italic" FontWeight="Light" Text="Browse *.xlsx file..." Grid.Column="1"/>
<Button Content="Browse..." Grid.Column="2"/>
</StackPanel>
</StackPanel>-->
<StackPanel Orientation="Horizontal">
<StackPanel Orientation="Vertical" Margin="5" Grid.Row="0">
<TextBlock MinHeight="20.5" Text="*.cfg File" Grid.Column="0"/>
<TextBlock MinHeight="20.5" Text="*.ps File " Grid.Column="0"/>
<TextBlock MinHeight="20.5" Text="*.pic File " Grid.Column="0"/>
<TextBlock MinHeight="20.5" Text="*.xlsx File" Grid.Column="0"/>
<TextBlock MinHeight="20.5" Text="*.xlsx File" Grid.Column="0"/>
</StackPanel>
<StackPanel Orientation="Vertical" Margin="5" Grid.Row="1">
<TextBox FontStyle="Italic" FontWeight="Light" Text="Browse *.cfg file..." Grid.Column="1" MinHeight="20.5"/>
<TextBox FontStyle="Italic" FontWeight="Light" Text="Browse *.ps file..." Grid.Column="1" MinHeight="20.5"/>
<TextBox FontStyle="Italic" FontWeight="Light" Text="Browse *.pic file..." Grid.Column="1" MinHeight="20.5"/>
<TextBox FontStyle="Italic" FontWeight="Light" Text="Browse Model mapping file..." Grid.Column="1" MinHeight="20.5"/>
<TextBox FontStyle="Italic" FontWeight="Light" Text="Browse Parameter mapping file..." Grid.Column="1" MinHeight="20.5"/>
</StackPanel>
<StackPanel Orientation="Vertical" Margin="5" Grid.Row="2">
<Button Content="Browse..." Grid.Column="2"/>
<Button Content="Browse..." Grid.Column="2"/>
<Button Content="Browse..." Grid.Column="2"/>
<Button Content="Browse..." Grid.Column="2"/>
<Button Content="Browse..." Grid.Column="2"/>
</StackPanel>
</StackPanel>
</DockPanel>
<DockPanel Grid.Column="1" Grid.Row="0">
<igDP:XamDataGrid x:Name="ItemsSource" DataContext="{Binding Source={StaticResource dataContext}, Path=ItemsSource, Mode=TwoWay}" Grid.Row="0" Margin="10" AutoFit="true">
<igDP:XamDataGrid.ViewSettings>
<igDP:GridViewSettings/>
</igDP:XamDataGrid.ViewSettings>
<igDP:XamDataGrid.FieldSettings>
<igDP:FieldSettings LabelTextAlignment="Left" AllowRecordFiltering="true" FilterOperandUIType="ExcelStyle" FilterStringComparisonType="CaseInsensitive" FilterOperatorDefaultValue="Contains"
LabelClickAction="SortByOneFieldOnlyTriState" SortComparisonType="Default"/>
</igDP:XamDataGrid.FieldSettings>
<igDP:XamDataGrid.FieldLayoutSettings>
<igDP:FieldLayoutSettings DataErrorDisplayMode="ErrorIconAndHighlight" SupportDataErrorInfo="RecordsAndCells" SelectionTypeRecord ="Single"
AutoGenerateFields="False" FilterUIType="FilterRecord"/>
</igDP:XamDataGrid.FieldLayoutSettings>
<igDP:XamDataGrid.FieldLayouts>
<igDP:FieldLayout>
<igDP:FieldLayout.Fields>
<igDP:Field Name="IsSelected" Label="Select" HorizontalContentAlignment="Left" Width="Auto" VerticalContentAlignment="Center">
<igDP:Field.Settings>
<igDP:FieldSettings DataItemUpdateTrigger="OnCellValueChange">
<igDP:FieldSettings.LabelPresenterStyle>
<Style TargetType="{x:Type igDP:LabelPresenter}">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<CheckBox Checked="CheckBox_Checked" Unchecked="CheckBox_Unchecked" Content="" />
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</igDP:FieldSettings.LabelPresenterStyle>
</igDP:FieldSettings>
</igDP:Field.Settings>
</igDP:Field>
<igDP:Field Label="Name" Name="Name" AllowEdit="False" HorizontalContentAlignment="Left" Width="Auto">
</igDP:Field>
<igDP:Field Label="Type" Name="Type" AllowEdit="False" HorizontalContentAlignment="Left" Width="*"/>
<igDP:Field Label="Background" Name="Background" AllowEdit="False" HorizontalContentAlignment="Left" Width="Auto"/>
<igDP:Field Label="Width" Name="Width" AllowEdit="False" HorizontalContentAlignment="Right" Width="Auto"/>
<igDP:Field Label="Height" Name="Height" AllowEdit="False" HorizontalContentAlignment="Right" Width="Auto"/>
</igDP:FieldLayout.Fields>
</igDP:FieldLayout>
</igDP:XamDataGrid.FieldLayouts>
</igDP:XamDataGrid>
</DockPanel>
<DockPanel Grid.Column="0" Grid.Row="1" Grid.RowSpan="2">
<StackPanel Orientation="Vertical" DockPanel.Dock="Bottom">
<TextBox Text="Sample Text1"/>
<TextBox Text="Sample Text2"/>
<TextBox Text="Sample Text3"/>
<TextBox Text="Sample Text4"/>
</StackPanel>
</DockPanel>
<!--</StackPanel>-->
</Grid>
</Window>
Xaml page code behind:
namespace UserInterface
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
//GraphicViewModel obj = new GraphicViewModel();
//ItemsSource.DataSource = obj.ItemsSource;
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
#endregion INotifyPropertyChanged Members
public GraphicViewModel GraphicViewModel
{
get { return this.DataContext as GraphicViewModel; }
set
{
this.DataContext = value;
if (this.DataContext != null)
NotifyPropertyChanged("GraphicViewModel");
}
}
private void CheckBox_Checked(object sender, RoutedEventArgs e)
{
}
private void CheckBox_Unchecked(object sender, RoutedEventArgs e)
{
}
}
}
Model Class:
namespace UserInterface.Model
{
public class GraphicsModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void NotifyOfPropertyChange(string property)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
private bool _isSelected;
public bool IsSelected
{
get { return _isSelected; }
set
{
if (_isSelected == value) return;
_isSelected = value;
NotifyOfPropertyChange("IsSelected");
}
}
private string _name = string.Empty;
public string Name
{
get { return _name; }
set
{
if (_name != value)
_name = value;
NotifyOfPropertyChange("Name");
}
}
private string _type = string.Empty;
public string Type
{
get { return _type; }
set
{
if (_type != value)
_type = value;
NotifyOfPropertyChange("Type");
}
}
private string _width = string.Empty;
public string Width
{
get { return _width; }
set
{
if (_width != value)
_width = value;
NotifyOfPropertyChange("Width");
}
}
private string _height = string.Empty;
public string Height
{
get { return _height; }
set
{
if (_height != value)
_height = value;
NotifyOfPropertyChange("Height");
}
}
}
}
ViewModel class:
namespace UserInterface.ViewModel
{
public class GraphicViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void NotifyOfPropertyChange(string property)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
private ObservableCollection<GraphicsModel> _itemsSource = new ObservableCollection<GraphicsModel>();
// MainWindow _view = null;
public ObservableCollection<GraphicsModel> ItemsSource
{
get { return _itemsSource; }
set
{
if (_itemsSource == value) return;
_itemsSource = value;
NotifyOfPropertyChange("ItemsSource");
}
}
public GraphicViewModel()
{
//_view = view;
_itemsSource = new ObservableCollection<GraphicsModel>() { new GraphicsModel() { Name = "sdasdad", Type = "Model", IsSelected = false, Height = "1000", Width = "1370" } ,
new GraphicsModel() { Name = "sdsa", Type = "Model", IsSelected = false, Height = "1000", Width = "1370" } ,new GraphicsModel() { Name = "sdasdad", Type = "Model", IsSelected = false, Height = "1000", Width = "1370" } ,new GraphicsModel() { Name = "asas", Type = "Model", IsSelected = false, Height = "1000", Width = "1370" } ,new GraphicsModel() { Name = "rewwe", Type = "Model", IsSelected = false, Height = "1000", Width = "1370" } ,};
//view.GraphicViewModel = this;
}
}
}
When you write
<Window.Resources>
<dc:GraphicViewModel x:Key="dataContext"/>
</Window.Resources>
You are saying "create a property of type GraphicViewModel and name it dataContext". It's almost the exact same as doing something like this in the code-behind :
private GraphicViewModel dataContext = new GraphicViewModel();
When you write
<igDP:XamDataGrid DataContext="{Binding Source={StaticResource dataContext}, Path=ItemsSource, Mode=TwoWay}" .. />
You are saying "bind the igDP:XamDataGrid.DataContext property to dataContext.ItemsSource".
Now for why the Grid won't load, the .DataContext property doesn't actually do anything. It's just a holder for the data that sits behind the control. So if you were to write
<igDP:XamDataGrid ItemsSource="{Binding MyProperty}" />
It would be to tell WPF "set XamDataGrid.ItemsSource property equal to XamDataGrid.DataContext.MyProperty".
Since in the code above you set the DataContext equal to dataContext.ItemsSource, it would try to set the value to dataContext.ItemsSource.MyProperty (which of course does not exist).
What you actually need is something like
<igDP:XamDataGrid ItemsSource="{Binding Source={StaticResource dataContext}, Path=ItemsSource}" .. />
This binds the .ItemsSource property of the grid (which is the property it builds its data rows from) to the static resource created in <Window.Resources> named "dataContext", and the property on that object called ItemsSource.
Second issue here though is you seem to have multiple copies of your ViewModel in your code. Personally I recommend never creating objects in the XAML like you did for your GraphicViewModel. Instead, I would recommend something like this :
public MainWindow()
{
InitializeComponent();
this.DataContext = new GraphicViewModel();
}
Now it should be noted that this creates a new instance of the GraphicViewModel, but doesn't store it anywhere. If you want to access this object in other code-behind without casting this.DataContext to GraphicViewModel, then you should probably store the value somewhere.
Once the Window.DataContext is set, you can write the bindings without specifying a custom Source property for the binding.
<igDP:XamDataGrid ItemsSource="{Binding ItemsSource}" .. />
This will work because WPF controls will look up the DataContext from their parent by default if it is not specifically set. So in this case, the .DataContext property for XamDataGrid is null so it will travel up the visual tree looking for something with a DataContext until it runs into Window.DataContext which you've set in the constructor to a new instance of your GraphicViewModel.
For people looking to understand the DataContext property, I usually send them to this SO answer to avoid having to retype the same thing all the time. I'd recommend reading it if you're still working to understand what the DataContext is or how it's used.
Also that said, Dependency Injection is something different and wouldn't be used here at all.
Thanks a lot #Rachel, #Daniel Filipov & #quetzalcoatl, I got my code working now. The changes done in below files:
MainWindow.xaml.cs
public MainWindow()
{
InitializeComponent();
ItemsSource.DataContext= new GraphicViewModel();
}
MainWindow.xaml:
<igDP:XamDataGrid x:Name="ItemsSource" DataSource="{Binding ItemsSource, Mode=TwoWay}" .../>
i,m try to learning wpf application. i try to use ninject for DI in WPF, and work perfectly. and then, i try to create login form. in this part i have some problem, i can't bind data from view to VM when the button clicked.
this my code
LoginUserControl
<UserControl x:Class="Middleware_v2._0_with_Modern_Ui.UserControls.LoginUserControl"
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:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:vm="clr-namespace:Middleware_v2._0_with_Modern_Ui.ViewModel"
xmlns:Custom="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:GalaSoft_MvvmLight_Command="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WPF4"
mc:Ignorable="d" DataContext="{Binding Login, Source={StaticResource Locator}}">
<Border Width="400" Height="300" BorderBrush="LightBlue" CornerRadius="5" Background="SkyBlue" Margin="0,-100,0,0">
<StackPanel Margin="0,0,10,0" Width="400">
<Label VerticalAlignment="Center" HorizontalAlignment="Center"
Content="Login Form" Margin="0,30,0,0" FontSize="20" FontWeight="Bold"/>
<Label Content="User Name" Margin="84,45,197,0"/>
<TextBox Text="{Binding UserName, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" Width="150" Height="25" Margin="165,-20,85,0"/>
<Label Content="Password" Margin="84,15,197,0"/>
<PasswordBox x:Name="txt_password" Width="150" Height="25" Margin="165,-20,85,0"/>
<Button Width="100" Height="30" Margin="-110,20,0,0" Content="Login" />
<Custom:Interaction.Triggers>
<Custom:EventTrigger EventName="Click">
<GalaSoft_MvvmLight_Command:EventToCommand x:Name="btnClicked" Command="{Binding Authorize, Mode=OneTime}"/>
</Custom:EventTrigger>
</Custom:Interaction.Triggers>
<!--<Button Width="100" Height="30" Margin="110,-30,0,200" Content="Exit" />-->
</StackPanel>
<Border.Effect>
<DropShadowEffect ShadowDepth="0" BlurRadius="15" Color="Gray" Direction="10"/>
</Border.Effect>
</Border>
LoginViewModel
public class LoginViewModel : ViewModelBase, ILoginViewModel
{
private readonly IAccountService _accountService;
public LoginViewModel(IAccountService _accountService)
{
this._accountService = _accountService;
Authorize = new RelayCommand(() => CheckAuthorized(), () => true);
}
public RelayCommand Authorize { get; set; }
private void CheckAuthorized()
{
User newUser = new User();
newUser.LoginName = _username;
newUser.LoginPassword = _password;
User user = _accountService.AuthenticationUser(newUser, 1);
throw new System.NotImplementedException();
}
}
LoginViewModel Interface
public interface ILoginViewModel
{
RelayCommand Authorize { get; set; }
}
how, to solve this? can some one help me
Simply
<Button Width="100" Height="30" Margin="-110,20,0,0" Content="Login" Command="{Binding Authorize}" />
I am total newbie to WPF. I am creating my custom user control which will display the employee data structure which is as follows I have implemented INotifyPropertyChanged also:
Here's code snippet
public class Employee : INotifyPropertyChanged
{
private int id;
private string name;
private double salary;
private EmployeeDesignation designation;
public int ID
{
get
{
return id;
}
set
{
id = value;
OnPropertyChanged(new PropertyChangedEventArgs("ID"));
//PropertyChanged(ID, new PropertyChangedEventArgs("ID"));
}
}
...
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (PropertyChanged != null)
{
PropertyChanged(this, e);
}
}
}
}
And user control code is as follows :
<UserControl x:Class="Assignment5.EmployeeUserControl"
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://scenter code herehemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d" DataContext="{Binding RelativeSource={RelativeSource Self}, Path=.}"
d:DesignHeight="196" d:DesignWidth="300">
<Grid Height="182">
<Label Content="Name" Height="28" HorizontalAlignment="Left" Margin="26,57,0,0" Name="label1" VerticalAlignment="Top" Width="76" />
<Label Content="Salary" Height="28" HorizontalAlignment="Left" Margin="26,91,0,0" Name="label2" VerticalAlignment="Top" />
<Label Content="ID" Height="28" HorizontalAlignment="Left" Margin="26,23,0,0" Name="label3" VerticalAlignment="Top" />
<Label Content="Designation" Height="28" HorizontalAlignment="Left" Margin="26,125,0,0" Name="label4" VerticalAlignment="Top" />
<TextBox Text="{Binding ElementName=Employee, Path=ID}" Height="23" HorizontalAlignment="Left" Margin="134,28,0,0" Name="IdTextBox" VerticalAlignment="Top" Width="120" />
<TextBox Text="{Binding ElementName=Employee, Path=Name}" Height="23" HorizontalAlignment="Left" Margin="134,59,0,0" Name="NameTextBox" VerticalAlignment="Top" Width="120" />
<TextBox Text="{Binding ElementName=Employee, Path=Salary}" Height="23" HorizontalAlignment="Left" Margin="134,91,0,0" Name="SalaryTextBox" VerticalAlignment="Top" Width="120" LostFocus="SalaryTextBoxLostFocus" />
<TextBox Text="{Binding ElementName=Employee, Path=designation}" Height="23" HorizontalAlignment="Left" Margin="134,125,0,0" Name="DesignationTextBox" VerticalAlignment="Top" Width="120" />
</Grid>
</UserControl>
Here's code behind file
namespace Assignment5
{
public partial class EmployeeUserControl : UserControl, INotifyPropertyChanged
{
public static readonly DependencyProperty EmpDependancyProperty =
DependencyProperty.Register("Employee", typeof(Employee), typeof(EmployeeUserControl)
, new PropertyMetadata(
new PropertyChangedCallback(
EmployeeUserControl.EmployeeDataChanged)));
public Employee Employee
{
get
{
return (Employee)GetValue(EmpDependancyProperty);
}
set
{
SetValue(EmpDependancyProperty, value);
}
}
public EmployeeUserControl()
{
InitializeComponent();
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
private void SalaryTextBoxLostFocus(object sender, RoutedEventArgs e)
{
MessageBox.Show(Employee.Name);
}
private static void EmployeeDataChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
EmployeeUserControl userControl = d as EmployeeUserControl;
userControl.OnPropertyChanged("Employee");
}
}
}
Here's my parent control...
<Window x:Class="Assignment5.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" xmlns:my="clr-namespace:Assignment5"
DataContext="{Binding RelativeSource={RelativeSource Self}, Path=.}">
<Grid>
<my:EmployeeUserControl Employee="{Binding Path=emp, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay, NotifyOnSourceUpdated=True, NotifyOnTargetUpdated=True}" HorizontalAlignment="Left" Margin="130,56,0,0" x:Name="employeeUserControl1" VerticalAlignment="Top" Width="285" />
</Grid>
</Window>
and a code behind :
namespace Assignment5
{
public partial class MainWindow : Window
{
public static readonly DependencyProperty EmpDependancyProperty =
DependencyProperty.Register("Employee", typeof(Employee), typeof(EmployeeUserControl)
, new PropertyMetadata(
new PropertyChangedCallback(
EmployeeUserControl.EmployeeDataChanged)));
public Employee Employee
{
get
{
return (Employee)GetValue(EmpDependancyProperty);
}
set
{
SetValue(EmpDependancyProperty, value);
}
}
public MainWindow()
{
emp = new Employee(203,"AAA",23232);
InitializeComponent();
}
}
}
When I run this code. I came to know that Employee object in parent control is getting initialized but in the user control it is not getting initialized. What I am doing wrong here?
Two issues
In your UserControl change the Bindings to
<TextBox Text="{Binding Path=Employee.ID}" Height="23" HorizontalAlignment="Left" Margin="134,28,0,0" Name="IdTextBox" VerticalAlignment="Top" Width="120" />
<TextBox Text="{Binding Employee.Name}" Height="23" HorizontalAlignment="Left" Margin="134,59,0,0" Name="NameTextBox" VerticalAlignment="Top" Width="120" />
<TextBox Text="{Binding Employee.Salary}" Height="23" HorizontalAlignment="Left" Margin="134,91,0,0" Name="SalaryTextBox" VerticalAlignment="Top" Width="120" LostFocus="SalaryTextBoxLostFocus" />
<TextBox Text="{Binding Employee.designation}" Height="23" HorizontalAlignment="Left" Margin="134,125,0,0" Name="DesignationTextBox" VerticalAlignment="Top" Width="120" />
In your Window:
<my:EmployeeUserControl Employee="{Binding Employee, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay, NotifyOnSourceUpdated=True, NotifyOnTargetUpdated=True}" HorizontalAlignment="Left" Margin="130,56,0,0" x:Name="employeeUserControl1" VerticalAlignment="Top" Width="285" />
In your constructor emp = new Employee(203,"AAA",23232); does not make any sense. Instead do this.Employee = new Employee(203,"AAA",23232);
Im having some problems with databinding inside a DataTemplate. In the ControlTemplate below the textbox in the Grid works and prints out the correct value. But the TextBlock inside the HyperlinkButtons DataTemplate does not work. Though the HyperlinkButtons NavigateUri is bound correctly. Could anyone plz help me with this
I have created a simple example that illustrates my problem.
MainPage.xaml
<UserControl x:Class="SilverlightApplication8.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"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<UserControl.Resources>
<ControlTemplate x:Key="EventControlTemplate" TargetType="Button">
<Grid>
<!--WORKS-->
<!--<Grid >
<TextBlock x:Name="TitleTextBlock" Text="{Binding Title}" Foreground="Red" FontWeight="Bold" />
</Grid>-->
<!--DOES NOT WORK-->
<HyperlinkButton TargetName="_blank" NavigateUri="{Binding Url}" >
<HyperlinkButton.ContentTemplate>
<DataTemplate>
<Grid>
<TextBlock Foreground="Green" Text="{Binding Title}"/>
</Grid>
</DataTemplate>
</HyperlinkButton.ContentTemplate>
</HyperlinkButton>
</Grid>
</ControlTemplate>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White">
<ItemsControl x:Name="Links" Foreground="White" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border >
<Button Template="{StaticResource EventControlTemplate}" Click="Button_Click"/>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</UserControl>
MainPage.xaml.cs
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
namespace SilverlightApplication8
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
List<Events> events = new List<Events>();
events.Add(new Events(){Title = "This is title 1", Url = "http://www.thesun.co.uk"});
events.Add(new Events(){Title = "This is title 2", Url = "http://www.thesun.co.uk"});
events.Add(new Events() { Title = "This is title 3", Url = "http://www.thesun.co.uk" });
Links.ItemsSource = events;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
}
}
public class Events
{
public string Url { get; set; }
public string Title { get; set; }
}
}
You're setting the ContentTemplate, the DataContext of which will be the Content of the HyperlinkButton. Since you haven't set the Content, you're attempting to bind against null.
This should work:
<HyperlinkButton TargetName="_blank" NavigateUri="{Binding Url}" Content="{Binding Title}">
<HyperlinkButton.ContentTemplate>
<DataTemplate>
<Grid>
<TextBlock Foreground="Green" Text="{Binding .}"/>
</Grid>
</DataTemplate>
</HyperlinkButton.ContentTemplate>
</HyperlinkButton>
But then that begs the question as to why you're even setting the ContentTemplate instead of just doing this:
<HyperlinkButton TargetName="_blank" NavigateUri="{Binding Url}" Content="{Binding Title}"/>
I have a datagrid on a view that is bound to a viewmodel. When I initialze the view, the datagrid is populated with data from the viewmodel (ObservableCollection) as it should. However, with I try to do a search against the data, the datagrid does not get refreshed from the viewmodel. When I breakpoint the code in my viewmodel, I can see the results in the ObservableCollection has changed per my search, but somehow that is not getting communicated back to the view. Here is my view and viewmodel (BTW, I am using VS2010 RTM):
namespace Attendance.ViewModels
{
public class EmployeeSelectViewModel : ViewModel, INotifyPropertyChanged
{
#region Entity list and constructor
public EmployeeSelectViewModel()
{
{
Initialize();
}
}
private void Initialize()
{
if (employeeRpository == null)
employeeRpository = new EmployeeRepository();
ListOfEmployees = new ObservableCollection<EmployeeDto>(employeeRpository.GetEmployees(true));
}
private EmployeeRepository employeeRpository;
private ObservableCollection<EmployeeDto> listOfEmployees;
public ObservableCollection<EmployeeDto> ListOfEmployees
{
get { return listOfEmployees; }
set
{
if (listOfEmployees != value)
{
listOfEmployees = value;
NotifyPropertyChanged("ListOfEmployee");
}
}
}
private EmployeeDto selectedEmployee;
public EmployeeDto SelectedEmployee
{
get { return selectedEmployee; }
set
{
if (selectedEmployee != value)
{
selectedEmployee = value;
NotifyPropertyChanged("SelectedEmployee");
}
}
}
#endregion
#region UI control references
/// <summary>
/// search text property
/// </summary>
private string searchText;
public string SearchText
{
get { return searchText; }
set
{
if (searchText != value)
{
searchText = value;
NotifyPropertyChanged("SearchText");
}
}
}
public string Location { get; set; }
#endregion
#region Relay Commands
/// <summary>
/// new command
/// </summary>
private ViewCommand newCommand;
public ViewCommand NewCommand
{
get
{
if (newCommand == null)
newCommand = new ViewCommand(param => this.NewEmployee());
return newCommand;
}
}
private void NewEmployee()
{
NavigationActions.NewEmployeeView();
}
/// <summary>
/// edit command
/// </summary>
private ViewCommand editCommand;
public ViewCommand EditCommand
{
get
{
if (editCommand == null)
{
editCommand = new ViewCommand(param => this.EditEmployee());
}
return editCommand;
}
}
private void EditEmployee()
{
NavigationActions.OpenEmployeeView(SelectedEmployee);
}
/// <summary>
/// save command
/// </summary>
private ViewCommand saveCommand;
public ViewCommand SaveCommand
{
get
{
if (saveCommand == null)
{
saveCommand = new ViewCommand(
param => this.SaveEmployee(),
param => this.CanSaveEmployee
);
}
return saveCommand;
}
}
public void SaveEmployee()
{
employeeRpository.SaveChanges();
}
private bool CanSaveEmployee
{
get { return true; }
}
/// <summary>
/// clear search command
/// </summary>
private ViewCommand clearSearchCommand;
public ViewCommand ClearSearchCommand
{
get
{
if (clearSearchCommand == null)
clearSearchCommand = new ViewCommand(param => this.ClearSearch());
return clearSearchCommand;
}
}
private void ClearSearch()
{
this.SearchText = string.Empty;
ListOfEmployees = new ObservableCollection<EmployeeDto>(employeeRpository.GetEmployees(true));
}
/// <summary>
/// search command
/// </summary>
private ViewCommand searchCommand;
public ViewCommand SearchCommand
{
get
{
if (searchCommand == null)
searchCommand = new ViewCommand(param => this.SearchEmployee());
return searchCommand;
}
}
private void SearchEmployee()
{
if (this.SearchText == string.Empty || this.SearchText == null)
{
NavigationActions.ShowError("Search Employees.", "Please enter your search text ...");
return;
}
ListOfEmployees = new ObservableCollection<EmployeeDto>(employeeRpository.GetEmployeesByQuery(SearchText, Location));
}
/// <summary>
/// exit command
/// </summary>
private ViewCommand exitCommand;
public ViewCommand ExitCommand
{
get
{
if (exitCommand == null)
{
exitCommand = new ViewCommand(param => this.ExitWindow());
}
return exitCommand;
}
}
private void ExitWindow()
{
NavigationActions.CloseCurrentView();
}
#endregion
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
#endregion
}
}
<Window x:Class="Attendance.Views.EmployeeSelectView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:Attendance.ViewModels"
Title="Employee Maintenance" FocusManager.FocusedElement="{Binding ElementName=txtSearchCriteria}"
Height="525" Width="800" WindowStartupLocation="CenterScreen" WindowState="Normal"
WindowStyle="SingleBorderWindow" Icon="Images/gb_icon.png">
<Window.DataContext>
<vm:EmployeeSelectViewModel />
</Window.DataContext>
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Themes/DataGrid.Generic.xaml" />
</ResourceDictionary.MergedDictionaries>
<!--xml data start-->
<XmlDataProvider x:Key="LocationData" XPath="LocationList/LocationItem" Source="XMLData/Location.xml"/>
<!--xml data end-->
</ResourceDictionary>
</Window.Resources>
<Grid Width="775">
<DockPanel HorizontalAlignment="Left" Width="770">
<!-- TOOLBAR -->
<DockPanel DockPanel.Dock="Top" MinHeight="30" Margin="5">
<ToolBar FontWeight="Bold">
<!-- NEW -->
<Button Name="btnNew" Command="{Binding Path=NewCommand}">
<Button.ToolTip>
<StackPanel>
<Label FontWeight="Bold" Background="SteelBlue" Foreground="White">
Create a new Customer
</Label>
<TextBlock Padding="10" TextWrapping="WrapWithOverflow" Width="200">
Create a new customer in a new Window tab.
</TextBlock>
<Line Stroke="SteelBlue" StrokeThickness="1" X2="200" />
<StackPanel Orientation="Horizontal">
<Image Margin="2" Source="Images/new.png"/>
<Label>Press F1 for more help</Label>
</StackPanel>
</StackPanel>
</Button.ToolTip>
<StackPanel Orientation="Horizontal">
<Image Source="Images/new.png" Width="22" Height="22" Margin="2"/>
<Label VerticalAlignment="Center">_New</Label>
</StackPanel>
</Button>
<!-- EDIT -->
<Button Name="btnEdit" Command="{Binding Path=EditCommand}">
<Button.ToolTip>
<StackPanel>
<Label FontWeight="Bold" Background="SteelBlue" Foreground="White">
Edit the current record
</Label>
<TextBlock Padding="10" TextWrapping="WrapWithOverflow" Width="200">
Edit the current selected Customer.
</TextBlock>
<Line Stroke="SteelBlue" StrokeThickness="1" X2="200" />
<StackPanel Orientation="Horizontal">
<Image Margin="2" Source="Images/dialog-information.png"/>
<Label>Press F1 for more help</Label>
</StackPanel>
</StackPanel>
</Button.ToolTip>
<StackPanel Orientation="Horizontal">
<Image Source="Images/edit.png" Width="22" Height="22" Margin="2" />
<Label VerticalAlignment="Center">_Edit</Label>
</StackPanel>
</Button>
<!-- SEARCH -->
<Separator />
<TextBox Name="txtSearchCriteria"
MinWidth="300" Margin="5"
BorderThickness="1" BorderBrush="LightGray"
FontWeight="Normal" Foreground="Gray" Text="{Binding Path=SearchText}">
</TextBox>
<Button Name="btnSearch" Command="{Binding Path=SearchCommand}">
<Button.ToolTip>
<StackPanel>
<Label FontWeight="Bold" Background="SteelBlue" Foreground="White">
Search
</Label>
<TextBlock Padding="10" TextWrapping="WrapWithOverflow" Width="200">
Search a specific Customer.
</TextBlock>
<Line Stroke="SteelBlue" StrokeThickness="1" X2="200" />
<StackPanel Orientation="Horizontal">
<Image Margin="2" Source="Images/find.png"/>
<Label>Press F1 for more help</Label>
</StackPanel>
</StackPanel>
</Button.ToolTip>
<StackPanel Orientation="Horizontal">
<Image Source="Images/find.png" Width="22" Height="22" Margin="2" />
<Label VerticalAlignment="Center">_Find</Label>
</StackPanel>
</Button>
<Button Name="btnClearSearch" Command="{Binding Path=ClearSearchCommand}">
<Button.ToolTip>
<StackPanel>
<Label FontWeight="Bold" Background="SteelBlue" Foreground="White">
Search
</Label>
<TextBlock Padding="10" TextWrapping="WrapWithOverflow" Width="200">
Clear search results.
</TextBlock>
<Line Stroke="SteelBlue" StrokeThickness="1" X2="200" />
<StackPanel Orientation="Horizontal">
<Image Margin="2" Source="Images/find.png"/>
<Label>Press F1 for more help</Label>
</StackPanel>
</StackPanel>
</Button.ToolTip>
<StackPanel Orientation="Horizontal">
<Label VerticalAlignment="Center">_Clear Search</Label>
</StackPanel>
</Button>
<!-- EXIT -->
<Separator />
<Button Name="btnExit" Command="{Binding Path=ExitCommand}">
<Button.ToolTip>
<StackPanel>
<Label FontWeight="Bold" Background="SteelBlue" Foreground="White">
Start the application
</Label>
<TextBlock Padding="10" TextWrapping="WrapWithOverflow" Width="200">
Start the main application with the M-V-MV pattern.
</TextBlock>
<Line Stroke="SteelBlue" StrokeThickness="1" X2="200" />
<StackPanel Orientation="Horizontal">
<Image Margin="2" Source="Images/dialog-information.png"/>
<Label>Press F1 for more help</Label>
</StackPanel>
</StackPanel>
</Button.ToolTip>
<StackPanel Orientation="Horizontal">
<Image Source="Images/exit.png" Width="22" Height="22" Margin="2" />
<Label VerticalAlignment="Center">_Exit</Label>
</StackPanel>
</Button>
</ToolBar>
</DockPanel>
<!-- LIST -->
<DockPanel DockPanel.Dock="Top" MinHeight="30" Margin="0,0,0,5">
<Label>Location:</Label>
<ComboBox Name="cboLocation" Grid.Column="1" Grid.Row="4"
ItemsSource="{Binding Source={StaticResource LocationData}}"
DisplayMemberPath="location_text" SelectedValuePath="location_value"
SelectedValue="{Binding Path=Location}"
HorizontalAlignment="Left" Width="175" Margin="4" />
</DockPanel>
<DockPanel Margin="5">
<DataGrid ItemsSource="{Binding Path=ListOfEmployees}" AutoGenerateColumns="False" IsReadOnly="True"
Name="dgEmployee" SelectionMode="Single" SelectionUnit="FullRow" CanUserResizeColumns="True"
SelectedItem="{Binding Path=SelectedEmployee}" GridLinesVisibility="Horizontal">
<DataGrid.Columns>
<DataGridTextColumn Header="Employee ID" Width="SizeToCells" MinWidth="125" Binding="{Binding EmployeeID}" />
<DataGridTextColumn Header="First Name" Width="SizeToCells" MinWidth="200" Binding="{Binding FirstName}" />
<DataGridTextColumn Header="Last Name" Width="SizeToCells" MinWidth="200" Binding="{Binding LastName}" />
<DataGridTextColumn Header="Location" Width="SizeToCells" MinWidth="125" Binding="{Binding Location}" />
<DataGridCheckBoxColumn x:Name="Active" Header="Active" Binding="{Binding active}" MinWidth="75" />
</DataGrid.Columns>
</DataGrid>
</DockPanel>
</DockPanel>
</Grid>
This was my solution:
<DataGrid Name="dgrid" ItemsSource="{Binding UserSettings, IsAsync=True}" AutoGenerateColumns="False">
The key being the setting of IsAsync=True, allows the screen paint to occur
I found 2 ways to refresh DataGrid:
One was posted by VariableLost, it works with INotifyPropertyChanged but have one drawback. Whole DataGrid is refreshed with blink effect (disappears for a split second). Doesn't look natural.
Other solution is to refresh ObservableCollection in ViewModel or Code Behind (if you're not using MVVM):
CollectionViewSource.GetDefaultView(collectionName).Refresh();
Looks more natural because only changes cells affected by edition.
Your previous code should have also worked, but 'magic strings' got in the way.
Property name is ListOfEmployees and in its setter you raise PropertyChanged event with property name ListOfEmployee. 's' is missing.
Beware of your new code. It will raise CollectionChanged event on ListOfEmployees for every insertion, and that might make your app slower if you are doing many insertions.
For many insertions, it would be better to derive from ObservableCollection and implement Reset method that clears underlying Items, adds new items and raises CollectionChanged event of type Reset.
My question was answered in a post on another site. Instead of creating a new instance of the ListOfEmployees in my view model, I just cleared the existing one and added the results from my repository:
private void SearchEmployee()
{
if (String.IsNullOrEmpty(this.SearchText) || String.IsNullOrEmpty(this.Location))
{
NavigationActions.ShowError("Search Employees.", "Please enter your search text and select a location...");
return;
}
// clear the list and repopulate based on the search criteria
if (ListOfEmployees != null)
{
ListOfEmployees.Clear();
IList<EmployeeDto> iList = employeeRpository.GetEmployeesByQuery(SearchText, Location, IsActive);
foreach (EmployeeDto value in iList)
ListOfEmployees.Add(value);
}
}
That did the trick.