Display Images (Binding) in Silverlight - silverlight

I need to solve following issue: In a Silverlight app, the user needs to be able to upload images to the client (not the server). The images should be displayed in a wrappanel.
I am a complete rookie to silverlight, so you might find several mistakes in the code. Below I posted the code, I hope it is sufficient to answer the question!
App.xaml:
<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Dojo_3_wi10b012.ViewModel"
x:Class="Dojo_3_wi10b012.App"
>
<Application.Resources>
<local:ViewModel x:Key="viewModel"/>
</Application.Resources>
</Application>
MainPage.xaml:
<UserControl x:Class="Dojo_3_wi10b012.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:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
xmlns:local="clr-namespace:Dojo_3_wi10b012.ViewModel"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<Grid x:Name="LayoutRoot" Background="White" DataContext="{StaticResource viewModel}">
<sdk:Frame Height="350" Width="450"
Name="frameContainer" Margin="0,0,0,0">
</sdk:Frame>
<Button Content="Add Image" Command="{Binding Path=AddImageCommand}" Height="23" HorizontalAlignment="Left" Margin="468,454,0,0" Name="buttonAddImage" VerticalAlignment="Top" Width="75" />
</Grid>
</UserControl>
Gallery.xaml:
<navigation:Page x:Class="Dojo_3_wi10b012.View.Gallery"
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:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:local="clr-namespace:Dojo_3_wi10b012.ViewModel"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignWidth="640" d:DesignHeight="480"
Title="Gallery Page"
NavigationCacheMode="Required" xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit">
<!-- trying to implement Mr. Eckkrammer's hint (wiki)-->
<UserControl.Resources>
<DataTemplate x:Key="galleryTemplate">
<Image>
<Image.Source>
<BitmapImage UriSource="{Binding Image}"/>
</Image.Source>
</Image>
</DataTemplate>
</UserControl.Resources>
<!-- END OF trying to implement Mr. Eckkrammer's hint (wiki)-->
<Grid x:Name="LayoutRoot" Height="350" Width="450" Background="Beige" DataContext="{StaticResource viewModel}">
<!-- "First attempt
<ItemsControl ItemsSource="{Binding ElementName=ImageDescrList, Path=Image ,Mode=TwoWay}" >
<ScrollViewer Width="449" Height="349" Margin="1,1,0,0">
<toolkit:WrapPanel Orientation="Horizontal" ItemWidth="90" ItemHeight="90" Width="Auto" />
</ScrollViewer>
</ItemsControl>
-->
<!-- 2nd attempt (Mr. Eckkrammer's hint (wiki): -->
<ItemsControl ItemsSource="{Binding ElementName=ImageDescrList}" ItemTemplate="{StaticResource galleryTemplate}">
<ScrollViewer Width="449" Height="349" Margin="1,1,0,0">
<toolkit:WrapPanel Orientation="Horizontal" ItemWidth="90" ItemHeight="90" Width="Auto" />
</ScrollViewer>
</ItemsControl>
</Grid>
</navigation:Page>
ImageDescription.cs:
namespace Dojo_3_wi10b012.Model
{
public class ImageDescription : INotifyPropertyChanged
{
private string _description;
private BitmapImage _image;
public string Description
{
get { return _description; }
set
{
_description = value;
NotifyPropertyChanged("Description");
}
}
public BitmapImage Image
{
get { return _image; }
set
{
_image = value;
NotifyPropertyChanged("Image");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
}
ViewModel.cs:
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.IO;
using System.IO.IsolatedStorage;
using System.Windows.Media.Imaging;
using System.Collections;
using System.Collections.ObjectModel;
using Dojo_3_wi10b012.Model;
using System.ComponentModel;
namespace Dojo_3_wi10b012.ViewModel
{
public class ViewModel : INotifyPropertyChanged
{
public RelayCommand AddImageCommand { get; private set; }
private ObservableCollection<ImageDescription> _imageDescrList = new ObservableCollection<ImageDescription>();
#region properties
public ObservableCollection<ImageDescription> ImageDescrList
{
get { return _imageDescrList; }
set
{
_imageDescrList = value;
NotifyPropertyChanged("ImageDescrList");
}
}
#endregion
#region Constructor
public ViewModel()
{
AddImageCommand = new RelayCommand(AddImage);
AddImageCommand.IsEnabled = true;
}
#endregion
#region private methods
private void AddImage()
{
//initial ideas: (copy paste + modified from source: http://msdn.microsoft.com/en-us/library/cc221415(v=vs.95).aspx )
// Create an instance of the open file dialog box.
OpenFileDialog openFileDialog1 = new OpenFileDialog();
// Set filter options and filter index.
openFileDialog1.Filter = "JPEG Files (.jpg)|*.jpg|PNG Files (.png)|*.png|GIF Files (.gif)|*.gif|BMP Files (.bmp)|*.bmp|TIFF Files (.tiff)|*.tiff";
openFileDialog1.FilterIndex = 1;
openFileDialog1.Multiselect = false;
// Call the ShowDialog method to show the dialog box.
bool? userClickedOK = openFileDialog1.ShowDialog();
// Process input if the user clicked OK.
if (userClickedOK == true)
{
// Open the selected file to read.
using (var filestream = openFileDialog1.File.OpenRead())
{
var buffer = new byte[filestream.Length];
filestream.Read(buffer, 0, buffer.Length);
//add the image to our list of images
MemoryStream ms = new MemoryStream(buffer, 0, buffer.Length);
BitmapImage temp = new BitmapImage();
temp.SetSource(ms);
ImageDescrList.Add(
new ImageDescription()
{
// Description = filestream.Name,
Description="Default Description",
Image = temp
}
);
ms.Close();
filestream.Close();
}
}
}
#endregion
#region event Handler (property changed)
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
}
}

Try this in your galleryTemplate template to bind the Image Source to your bitmap:
<DataTemplate x:Key="galleryTemplate">
<Image Source="{Binding Image}"/>
</DataTemplate>
You appear to be trying to bind a bitmap UriSource to a Bitmap instead (that would expect a Uri):
<DataTemplate x:Key="galleryTemplate">
<Image>
<Image.Source>
<BitmapImage UriSource="{Binding Image}"/>
</Image.Source>
</Image>
</DataTemplate>

Related

WPF - MVVM binding in UserControl

I'm testing a sample binding in MVVM pattern. I'm using package GalaSoft.MvvmLight. Binding from MainViewModel to MainWindow is normal but I can't binding data from a ViewModel (ImageViewModel) to View (ImageView). All my code is below
in App.xaml
<Application x:Class="WpfApplication1.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-
namespace:WpfApplication1" StartupUri="MainWindow.xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" d1p1:Ignorable="d"
xmlns:d1p1="http://schemas.openxmlformats.org/markup-compatibility/2006">
<Application.Resources>
<ResourceDictionary>
<vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" xmlns:vm="clr-
namespace:WpfApplication1.ViewModel" />
</ResourceDictionary>
</Application.Resources>
</Application>
in MainWindow.xaml
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:v="clr-namespace:WpfApplication1.View"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication1"
DataContext="{Binding Main, Source={StaticResource Locator}}"
mc:Ignorable="d"
Title="MainWindow" Height="800" Width="1000">
<Grid>
<Grid Grid.Column="1">
<v:ImageView DataContext="{Binding ImageVM}"/>
</Grid>
</Grid>
in ImageView.xaml
<UserControl x:Class="WpfApplication1.View.ImageView"
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:WpfApplication1.View"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
Name="ucImage">
<UserControl.DataContext>
<Binding Path="Main.ImageVM" Source="{StaticResource Locator}"/>
</UserControl.DataContext>
<Grid>
<TextBox x:Name="label" Text="{Binding TestText, ElementName=ucImage}" Width="100"
Height="50"/>
</Grid>
</UserControl>
in ViewModelLocator.cs
using GalaSoft.MvvmLight;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WpfApplication1.ViewModel
{
public class ImageViewModel: ViewModelBase
{
public string _TestText;
public string TestText
{
get
{
return _TestText;
}
set
{
_TestText = value;
RaisePropertyChanged(() => this.TestText);
}
}
public ImageViewModel()
{
TestText = "asdasdasdasdas";
}
}
}
in MainViewModel
public class MainViewModel : ViewModelBase
{
private ImageViewModel _ImageVM;
public ImageViewModel ImageVM
{
get { return _ImageVM; }
set { Set(ref _ImageVM, value); }
}
public MainViewModel()
{
ImageVM = new ImageViewModel();
}
}
in ImageViewModel.cs
using GalaSoft.MvvmLight;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WpfApplication1.ViewModel
{
public class ImageViewModel: ViewModelBase
{
public string _TestText;
public string TestText
{
get
{
return _TestText;
}
set
{
_TestText = value;
RaisePropertyChanged(() => this.TestText);
}
}
public ImageViewModel()
{
TestText = "asdasdasdasdas";
}
}
}
This error from output is
System.Windows.Data Error: 40 : BindingExpression path error:
'TestText' property not found on 'object' ''ImageView'
(Name='ucImage')'. BindingExpression:Path=TestText;
DataItem='ImageView' (Name='ucImage'); target element is 'TextBox'
(Name='label'); target property is 'Text' (type 'String')
Anyone who comes up with a solution would be greatly appreciated!
The expression
Text="{Binding TestText, ElementName=ucImage}"
expects a TestText property in the ImageView control, which apperently does not exists - that is what the error message says.
You would simply write the following to make the element in the control's XAML bind directly to the view model object in its DataContext:
<TextBox Text="{Binding TestText}" .../>
In order to make the control independent of a specific view model, it should expose a bindable property, i.e. a dependency property like this:
public partial class ImageView : UserControl
{
public ImageView()
{
InitializeComponent();
}
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register(
nameof(Text), typeof(string), typeof(ImageView));
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
}
which would work with
<TextBox Text="{Binding Text, ElementName=ucImage}"
in the control's XAML and without explictly setting the control's DataContext, i.e. without the <UserControl.DataContext> section in its XAML.
The property would be bound like
<v:ImageView DataContext="{Binding ImageVM}" Text="{Binding TestText}"/>
or just
<v:ImageView Text="{Binding ImageVM.TestText}"/>

WPF: Dynamic views based on button clicks

I am a newbie to WPF and while I have read lots of theory and articles, I am unable to put it all together in a working solution.
Presently, I wish to implement dynamic multiple views in a window which could be selected by the user using buttons. The target is very much like one given in the question,
WPF : dynamic view/content
Can somebody please share with me a working code, of simplest implementation of the above. Just a window which contains two grids - one grid has two buttons - second grid changes background color depending on which button is clicked. From there on , I can take things further.
Thank you very much.
Use MVVM
It's a design approach. Basically you treat your Window as shell, and it's responsible for swapping views.
To simplify this snippet, I've referenced MvvmLight .
The Window contains ContentControl which dynamically displays the relevant view
Each dynamic view can communicate with the shell Window (using MvvmLight's Messenger) and tell it to change the view to something else.
MainWindow.xaml
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:MainWindowViewModel></local:MainWindowViewModel>
</Window.DataContext>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="20"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Button Grid.Row="0" Grid.Column="0" Command="{Binding ChangeFirstViewCommand}">Change View #1</Button>
<Button Grid.Row="0" Grid.Column="1" Command="{Binding ChangeSecondViewCommand}">Change View #2</Button>
<ContentControl Grid.Row="1" Grid.ColumnSpan="2" Content="{Binding ContentControlView}"></ContentControl>
</Grid>
</Window>
MainWindowViewModel.cs
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
namespace WpfApplication1
{
public class MainWindowViewModel : ViewModelBase
{
private FrameworkElement _contentControlView;
public FrameworkElement ContentControlView
{
get { return _contentControlView; }
set
{
_contentControlView = value;
RaisePropertyChanged("ContentControlView");
}
}
public MainWindowViewModel()
{
Messenger.Default.Register<SwitchViewMessage>(this, (switchViewMessage) =>
{
SwitchView(switchViewMessage.ViewName);
});
}
public ICommand ChangeFirstViewCommand
{
get
{
return new RelayCommand(() =>
{
SwitchView("FirstView");
});
}
}
public ICommand ChangeSecondViewCommand
{
get
{
return new RelayCommand(() =>
{
SwitchView("SecondView");
});
}
}
public void SwitchView(string viewName)
{
switch (viewName)
{
case "FirstView":
ContentControlView = new FirstView();
ContentControlView.DataContext = new FirstViewModel() { Text = "This is the first View" };
break;
default:
ContentControlView = new SecondView();
ContentControlView.DataContext = new SecondViewModel() { Text = "This is the second View" };
break;
}
}
}
}
FirstView.xaml
<UserControl x:Class="WpfApplication1.FirstView"
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="300" d:DesignWidth="300">
<StackPanel>
<Label>This is the second view</Label>
<Label Content="{Binding Text}" />
<Button Command="{Binding ChangeToSecondViewCommand}">Change to Second View</Button>
</StackPanel>
</UserControl>
FirstViewModel.cs
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace WpfApplication1
{
public class FirstViewModel : ViewModelBase
{
private string _text;
public string Text
{
get { return _text; }
set
{
_text = value;
RaisePropertyChanged("Text");
}
}
public ICommand ChangeToSecondViewCommand
{
get
{
return new RelayCommand(() =>
{
Messenger.Default.Send<SwitchViewMessage>(new SwitchViewMessage { ViewName = "SecondView" });
});
}
}
}
}
SecondView.xaml
<UserControl x:Class="WpfApplication1.SecondView"
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="300" d:DesignWidth="300">
<StackPanel>
<Label>This is the second view</Label>
<Label Content="{Binding Text}" />
<Button Command="{Binding ChangeToFirstViewCommand}">Change to First View</Button>
</StackPanel>
</UserControl>
SecondViewModel.cs
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace WpfApplication1
{
public class SecondViewModel : ViewModelBase
{
private string _text;
public string Text
{
get { return _text; }
set
{
_text = value;
RaisePropertyChanged("Text");
}
}
public ICommand ChangeToFirstViewCommand
{
get
{
return new RelayCommand(() =>
{
Messenger.Default.Send<SwitchViewMessage>(new SwitchViewMessage { ViewName = "FirstView" });
});
}
}
}
}
SwitchViewMessage.cs
namespace WpfApplication1
{
public class SwitchViewMessage
{
public string ViewName { get; set; }
}
}

Wpf TabControl Interaction.Trigger fires mores than once

I have an unexpected behaviour with a Wpf-Tabcontrol and Dataemplate with Interaction.Trgiggers.
First I define a "ViewModel". It's quite simple:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.ComponentModel;
using System.Windows;
using System.Windows.Input;
namespace WpfApplication3 {
public class Vm: INotifyPropertyChanged {
public Vm() {
this.CmdClick = new RelayCommand( p => this.ExecuteClick(), p => this.CanExecuteClick() );
}
private string myName;
public string MyName {
get { return myName; }
set {
if( myName != value ) {
myName = value;
if( this.PropertyChanged != null ) {
this.PropertyChanged( this, new PropertyChangedEventArgs( "MyName" ) );
}
}
}
}
private RelayCommand cmdClick;
public RelayCommand CmdClick {
get { return cmdClick; }
set { cmdClick = value; }
}
#region Command
private bool CanExecuteClick() {
return true;
}
public void ExecuteClick() {
MessageBox.Show( "MyName is " + MyName );
}
#endregion
public event PropertyChangedEventHandler PropertyChanged;
}
}
Next, I define a Datatemplate:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:l="clr-namespace:WpfApplication3"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<DataTemplate DataType="{x:Type l:Vm}" x:Key="Vm">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBox Text="{Binding Path=MyName}" Grid.Row="0"/>
<i:Interaction.Triggers>
<ei:KeyTrigger Key="F5" ActiveOnFocus="True" FiredOn="KeyUp" >
<i:InvokeCommandAction Command="{Binding CmdClick}" />
</ei:KeyTrigger>
</i:Interaction.Triggers>
</Grid>
</DataTemplate>
</ResourceDictionary>
I use the datatemplate on the mainform inside a TabControl:
<Window x:Class="WpfApplication3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:l="clr-namespace:WpfApplication3"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Dictionary1.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<TabControl>
<TabItem Header="Tab1">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ContentControl ContentTemplate="{StaticResource Vm}" x:Name="vm11" Content="{Binding}" Grid.Row="0"/>
</Grid>
</TabItem>
<TabItem Header="Tab2">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ContentControl ContentTemplate="{StaticResource Vm}" x:Name="vm21" Content="{Binding}" Grid.Row="0"/>
<ContentControl ContentTemplate="{StaticResource Vm}" x:Name="vm22" Content="{Binding}" Grid.Row="1"/>
</Grid>
</TabItem>
</TabControl>
</Window>
The code behind is simple:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfApplication3 {
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
this.vm11.Content = vm1;
this.vm21.Content = vm2;
this.vm22.Content = vm3;
this.vm1.MyName = "Name1";
this.vm2.MyName = "Name2";
this.vm3.MyName = "Name3";
}
Vm vm1 = new Vm();
Vm vm2 = new Vm();
Vm vm3 = new Vm();
}
}
When i run the program, I chlick in the first TextBox, press F5 and the MessageBox posup. Ok.
I switch the tabpage, click inside the second TextBox, press F5 and the MessageBox appears again. OK.
I switch back to the firsz tabpage, press F5 and the MessageBox appears twice. Uuuh. Whatss wrong.
I switch back to the second tabpage,the messagebox appears twice again.
After switching to the first tabpage, the messagebox is displayed treetimes now. And so on.
It is like, the KeyUp-Event is assigned internaly, when the datatemplate is displayed again, without dereferencing it. But ehat can I do ?
I think you need to change this property from
private RelayCommand cmdClick;
public RelayCommand CmdClick {
get { return cmdClick; }
set { cmdClick = value; }
To
private RelayCommand cmdClick;
public RelayCommand CmdClick {
get { return cmdClick; }
set { if(cmdClick == null)cmdClick = value; }

Binding List<string> property to Listbox WPF

Can someone help me? I have the folowing XAML code in my MainWindow.xaml file:
<ListBox ItemsSource="{Binding Files}" HorizontalAlignment="Left"
Height="371" Margin="281,53,0,0" VerticalAlignment="Top"
Width="609">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
And in my ViewModel.cs I have property:
public List<string> Files { get; set; }
But, when I click the button and add some items to Files nothing happens.
P.S. Sorry for my bad English :)
List does not implement INotifyCollectionChanged, instead of List, use ObservableCollection<string>
Additional Info: List vs ObservableCollection vs INotifyPropertyChanged
Here is your solution, just add this code and press 'Add String' button to make it work. I have used 'ObservableCollection' instead of List and made to listen it using 'INotifyPropertyChanged' interface in ViewModel.cs class
MainWindow.xaml
<Window x:Class="ListBox_Strings.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:myApp="clr-namespace:ListBox_Strings"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<myApp:ViewModel/>
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<ListBox ItemsSource="{Binding Files}" HorizontalAlignment="Left"
VerticalAlignment="Top" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button Grid.Row="1" Content="Add String" Click="Button_Click"></Button>
</Grid>
</Window>
MainWindow.xaml.cs
using System.Windows;
namespace ListBox_Strings
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
var vm = this.DataContext as ViewModel;
vm.Files.Add("New String");
}
}
}
ViewModel.cs
using System.Collections.ObjectModel;
using System.ComponentModel;
namespace ListBox_Strings
{
public class ViewModel:INotifyPropertyChanged
{
private ObservableCollection<string> m_Files;
public ObservableCollection<string> Files
{
get { return m_Files; }
set { m_Files = value;
OnPropertyChanged("Files"); }
}
public ViewModel()
{
Files = new ObservableCollection<string>();
Files.Add("A");
Files.Add("B");
Files.Add("C");
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string name)
{
if (PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
}
}

Trying to bind TextBlock which is inside the DataTemplate of an accordion control in Silverlight. Text is not visible when I run the application

I amsomewhat new to Silverlight, What I want to do is to show the Title in the accordion control which is bound from the property of that user control. I have a TextBlock which is inside the DataTemplate of an Accordion control in Silverlight. When I run the application, text is coming blank and nothing is displayed in the Accordion title.
<UserControl x:Class="SilverlightApplication1.SilverlightControl1"
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:layoutToolkit="clr- namespace:System.Windows.Controls;assembly=System.Windows.Controls.Layout.Toolkit"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400" DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid x:Name="LayoutRoot" Background="White">
<layoutToolkit:Accordion x:Name="accordionFilter" HorizontalAlignment="Stretch" SelectionMode="ZeroOrMore">
<layoutToolkit:AccordionItem MinHeight="0" MaxHeight="120" IsSelected="True">
<layoutToolkit:AccordionItem.HeaderTemplate>
<DataTemplate>
<Grid Height="22" VerticalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock
Text="{Binding MainPageSelectedText}"
Width="150"></TextBlock>
</Grid>
</DataTemplate>
</layoutToolkit:AccordionItem.HeaderTemplate>
</layoutToolkit:AccordionItem>
</layoutToolkit:Accordion>
</Grid>
</UserControl>
using System;
using System.ComponentModel;
using System.Windows.Controls;
namespace SilverlightApplication1
{
public partial class SilverlightControl1 : UserControl, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string name)
{
PropertyChangedEventHandler ph = this.PropertyChanged;
if (ph != null)
ph(this, new PropertyChangedEventArgs(name));
}
public SilverlightControl1()
{
InitializeComponent();
MainPageSelectedText = "Sample Text";
}
public string MainPageSelectedText
{
get { return _MainPageSelectedText; }
set
{
string myValue = value ?? String.Empty;
if (_MainPageSelectedText != myValue)
{
_MainPageSelectedText = value;
OnPropertyChanged("MainPageSelectedText");
}
}
}
private string _MainPageSelectedText;
}
}
On your data template level you don't have direct access to the user control's DataContext so your binding should look sth like:
Text="{Binding MainPageSelectedText, ElementName=MyUserControl}"
assuming that you will set Name/x:Name of your user control to MyUserControl.

Resources