I am trying to send to a view model the current item of a FlipView control, using MVVM Light.
The XAML code representing the FlipView control is the following:
<FlipView x:Name="mainFlipView" Margin="0,10,0,10" ItemsSource="{Binding AlbumItems, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<FlipView.ItemTemplate>
<DataTemplate>
<Grid Margin="5">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock Text="{Binding Caption}"
FontSize="23"
HorizontalAlignment="Center"
TextAlignment="Center"
TextWrapping="Wrap"
Margin="10"/>
<ScrollViewer Grid.Row="1" ZoomMode="Enabled">
<uc:ImageViewer FilePath="{Binding ImagePath}" />
</ScrollViewer>
<TextBlock Text="{Binding NrOfVotes}" FontSize="20"
Grid.Row="2" HorizontalAlignment="Center"
Margin="10" />
</Grid>
</DataTemplate>
</FlipView.ItemTemplate>
</FlipView>
...
The XAML code of the item containing the relay command is:
<Page.BottomAppBar>
<CommandBar>
<AppBarButton x:Name="appBarButtonDelete" Label="Delete" Icon="Delete"
Command="{Binding DeleteItemCommand}"
CommandParameter="{Binding ElementName=mainFlipView, Path=SelectedItem}"/>
</CommandBar>
</Page.BottomAppBar>
In the ViewModel, the RelayCommand is declared and used as follows:
public class ResultsPageViewModel : ViewModelBase
{
public RelayCommand<MyModel> DeleteItemCommand { get; private set; }
public ResultsPageViewModel()
{
this.DeleteItemCommand = new RelayCommand<MyModel>(post => DeleteItem(post));
}
public void DeleteItem(MyModel p)
{
//P is always null here...
}
}
The problem is that in the DeleteItem function I always get the parameter as null. I have tried declaring the RelayCommand as RelayCommand<object> but the problem persists.
I also tried the "workaround" method of declaring a MyModel bindable property and binding it to the FlipView. It works, but I would like to know what am I doing wrong in this situation.
Thank you in advance!
Try a different strategy: take the parameter directly from ViewModel, after a proper binding.
XAML
<FlipView x:Name="mainFlipView"
Margin="0,10,0,10"
ItemsSource="{Binding AlbumItems, Mode=TwoWay }"
SelectedItem="{Binding AlbumSelectedItem, Mode=TwoWay}">
ViewModel
private MyModel albumSelectedItem;
public MyModel AlbumSelectedItem
{
get
{
return albumSelectedItem;
}
set
{
if (value != null && albumSelectedItem != value)
{
albumSelectedItem = value;
RaisePropertyChanged(() => AlbumSelectedItem);
}
}
}
public void DeleteItem(MyModel p)
{
//P is always null here...
var pp = AlbumSelectedItem;
}
Obviously, CommandParameter is useless. ;-)
Related
I have added the template based on this link
I have an Add button - when I click on it through Command I add it to a collection.
<ItemsControl ItemsSource="{Binding Collection}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid DataContext="{StaticResource VieWModel}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="15*"/>
<ColumnDefinition Width="40*"/>
</Grid.ColumnDefinitions>
<Label Content="GH" Grid.Row="0" Grid.Column="0" VerticalContentAlignment="Center"></Label>
<tk:RadComboBox Grid.Row="0" Grid.Column="0" Margin="10" IsFilteringEnabled="True" Width="150" DisplayMemberPath="D" IsEditable="True" ItemsSource="{Binding GK}" SelectedItem="{Binding SK, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding SelectionChangedCommand}" CommandParameter="{Binding}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</tk:RadComboBox>
<Label Content="HB" Grid.Row="0" Grid.Column="1" VerticalContentAlignment="Center"></Label>
<tk:RadComboBox Grid.Row="0" Grid.Column="1" Margin="10" IsFilteringEnabled="True" Name="cb" Width="350" IsEditable="True" DisplayMemberPath="D" ItemsSource="{Binding VR}" SelectedItem="{Binding VR1,Mode=TwoWay}">
</tk:RadComboBox>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
ViewModel sample code:
// Property for selected Item in combox1
Public ValBase SK{get;set;}
//Property off combobox1 binding
Public ValBase GK{get;set;}
// Property ofor selected Item in combox2
Public ValBase VR1{get; set;}
//Property ofr combobox2 binding
Public ValBase VR{get;set;}
Public void AddButton(object obj)
{
var item =new collectionbase();
Collection.Add(item)
}
Whenever I click the Add Button this itemplate will be added.
MyRequirement :
When I Click Add Button for the first time ,template should get added
When I click Add Button for the second time Previous generated controls Must have contain the values,only then controls should be added to a collection and then new controls should be created
And I dont know how to save those values dynamically created in a collection
I am running out of Ideas how to achieve this can anyone help . MVVM pattern
I guess you are having Collection in MainViewModel and Command for add Model.
private Model _lastAdded;
public Model LastAdded
{
get{return _lastAdded;}
set{_lastAdded = value;}
}
private void AddCommand(object obj)
{
if(_lastAdded != null && _lastAdded.SelectedValue != null)
{
var newItem = new Model();
Collection.Add(newItem);
_lastAdded = newItem;
}
else
{
//Show message
}
}
Using Selector Class.I have used CurrentInstance To Bind the Collection its working fine now
I don't know why but my Visibility Binding isn't working ONLY in the DataTemplate. Did I forget something?
Edit: All Bindings (except for this one work perfectly)
Thats the structure.
<Window>
<Grid>
<Grid>
<Grid Grid.Row="5">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ItemsControl x:Name="Targets" Margin="0,4,0,4">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Margin="0,5,0,5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBox TextWrapping="Wrap" Foreground="{Binding Foreground, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}" Text="{Binding Address, UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True}" Tag="{Binding}" PreviewKeyDown="ChangeLocationAddress" PreviewGotKeyboardFocus="TxtGotKeyboardFocusHandler" LostKeyboardFocus="ChangeLocationAddress" />
<Button Margin="2,0,0,0" Grid.Column="1" Content=" ↑ " Click="MoveLocationUp" Visibility="Visible" />
<Button Margin="2,0,0,0" Grid.Column="2" Content=" ↓ " Click="MoveLocationDown" Visibility="{Binding Path = UpDownButtonVisibility, UpdateSourceTrigger=PropertyChanged}"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<Button x:Name="btnNewAddress" Grid.Row="1" Content="Neues Ziel hinzufügen" Margin="0,4,0,4" Visibility="{Binding Path=TargetButtonVisibility}"/>
</Grid>
</Grid></Grid></Grid></Window>
Codebehind:
public MapView(){
this.DataContext = this.ViewModel = new MapVM();
this.InitializeComponent();
this.Targest.Itemssource = this.ViewModel.ToLocations;
}
ViewModel:
public MapVM()
{ this.UpDownButtonVisibility = Visibility.Collapsed;
this.TargetButtonVisibility = Visibility.Collapsed;
}
private Visibility _UpDownButtonVisibility;
/// <summary>
/// Property Visibility für "↓" und "↑"
/// </summary>
public Visibility UpDownButtonVisibility
{
get { return _UpDownButtonVisibility; }
set
{
this._UpDownButtonVisibility = value;
NotifyPropertyChanged("UpDownButtonVisibility");
}
}
public Visibility TargetButtonVisibility { get; set; }
EDIT:
Program Output:
BindingExpression path error: 'UpDownButtonVisibility' property not found on 'object' ''Location' (HashCode=-794088449)'. BindingExpression:Path=UpDownButtonVisibility; DataItem='Location' (HashCode=-794088449); target element is 'Button' (Name=''); target property is 'Visibility' (type 'Visibility') 1.10s
Any suggestions?
I cannot find a PropertyChanged event handler and a call to it in your code. Add the INotifyPropertyChanged to your DataContext object and it should work
Personally I would model the visibility as a bool and use the BooleasnToVisibility Converter that comes with WPF.
Change string to Visibility
public Visibility UpDownButtonVisibility { get; set; }
this.UpDownButtonVisibility = Visibility.Collapsed;
Add INPC and binding to a View model.
Here is working sample:
XAML
<Window x:Class="ItemsControlDataTemplate.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:ItemsControlDataTemplate"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:MainWindowViewModel />
</Window.DataContext>
<Grid>
<ItemsControl x:Name="Targets" Margin="0,4,0,4" ItemsSource="{Binding Items}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Margin="0,5,0,5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBox TextWrapping="Wrap" Foreground="{Binding Foreground, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}" Text="{Binding Address, UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True}" Tag="{Binding}" />
<Button Margin="2,0,0,0" Grid.Column="1" Content=" ↑ " Visibility="Visible" />
<Button Margin="2,0,0,0" Grid.Column="2" Content=" ↓ " Visibility="{Binding Path=UpDownButtonVisibility}"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</Window>
C#
class MainWindowViewModel : INotifyPropertyChanged
{
ObservableCollection<MapVM> _items = new ObservableCollection<MapVM>();
public ObservableCollection<MapVM> Items { get { return _items; } }
public MainWindowViewModel()
{
Items.Add(new MapVM() { UpDownButtonVisibility = Visibility.Visible, Address = "1111111" });
Items.Add(new MapVM() { UpDownButtonVisibility = Visibility.Collapsed, Address = "222222" });
Items.Add(new MapVM() { UpDownButtonVisibility = Visibility.Visible, Address = "33333333" });
}
public event PropertyChangedEventHandler PropertyChanged;
}
class MapVM : INotifyPropertyChanged
{
public MapVM()
{
this.UpDownButtonVisibility = Visibility.Collapsed;
this.TargetButtonVisibility = Visibility.Collapsed;
}
private Visibility _upDownButtonVisibility;
public Visibility UpDownButtonVisibility
{
get { return _upDownButtonVisibility; }
set
{
_upDownButtonVisibility = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(UpDownButtonVisibility)));
}
}
private Visibility _targetButtonVisibility;
public Visibility TargetButtonVisibility
{
get { return _targetButtonVisibility; }
set
{
_targetButtonVisibility = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(TargetButtonVisibility)));
}
}
private string _address;
public string Address
{
get { return _address; }
set
{
_address = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Address)));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
The DataContext of your TargetButtonVisibility binding is your main MapVM. This works ok.
The DataContext within your DataTemplate is not MapVM, is it the item being displayed by the template.
Since you have not supplied any ItemsSource binding on your ItemsControl we have no way of knowing what this actually is.
Also, as unkreativ points out, do not use Visibility in your VM, since this is a view related type. Use bool instead and call the property IsUpDownButtonVisible or similar.
EDIT: Assuming you do actually want to bind to your single MapVM, you could use a RelativeSource to find the parent ItemsControl:
<Button Margin="2,0,0,0"
Grid.Column="2"
Content=" ↓ "
Click="MoveLocationDown"
Visibility="{Binding DataContext.UpDownButtonVisibility,
RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ItemsControl}}"/>
However, since you've already named your ItemsControl (Targets), you can simply refer to it by name:
<Button Margin="2,0,0,0"
Grid.Column="2"
Content=" ↓ "
Click="MoveLocationDown"
Visibility="{Binding DataContext.UpDownButtonVisibility,
ElementName=Targets}"/>
Here is my problem i need to solve.
My data content is in DemoList class:
NOTICE: DemoHeader object contains a ObservableCollection of DemoItem objects, and DemoList object contains ObservableCollection of DemoHeader objects
public enum Type
{
article,
product,
material
}
public class DemoHeader
{
private ObservableCollection<DemoItem> _items;
public ObservableCollection<DemoItem> Items
{
get { return _items; }
set { _items = value; }
}
public DemoHeader(string document)
{
this._salesOrder = document;
_items = new ObservableCollection<DemoItem>();
}
private string _salesOrder;
public string SalesOrder
{
get { return _salesOrder; }
set { _salesOrder = value; }
}
}
public class DemoItem
{
public DemoItem(string name, Type type)
{
this._name = name;
this._type = type;
}
private Type _type;
public Type Type
{
get { return _type; }
set { _type = value; }
}
private string _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
}
public class DemoList : ObservableCollection<DemoHeader>//, ICollectionView
{
public DemoList()
{
DemoHeader dd = new DemoHeader("Doc-1");
dd.Items.Add(new DemoItem("T-1", Type.article));
dd.Items.Add(new DemoItem("M-1", Type.material));
DemoHeader dd2 = new DemoHeader("Doc-2");
dd2.Items.Add(new DemoItem("P-1", Type.product));
dd2.Items.Add(new DemoItem("P-2", Type.product));
this.Add(dd);
this.Add(dd2);
}
}
XAML:
NOTICE: I have 4 CollectionViewSource for each ListBox.
<Window x:Class="WuZet.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:c="clr-namespace:WuZet"
Title="WuZet" WindowStartupLocation="CenterScreen" ResizeMode="CanResize" Loaded="window_loaded" Background="#ECE9D8" WindowStyle="ToolWindow" Icon="/WuZet;component/Images/ksi_ikona.ico" Topmost="True" WindowState="Maximized" SizeToContent="WidthAndHeight">
<Window.Resources>
<CollectionViewSource x:Key="list" Source="{Binding}"></CollectionViewSource>
<CollectionViewSource x:Key="wares" Source="{Binding Source={StaticResource list}, Path=Items}" Filter="wareFilter"></CollectionViewSource>
<CollectionViewSource x:Key="materials" Source="{Binding Source={StaticResource list}, Path=Items}" Filter="materialFilter"></CollectionViewSource>
<CollectionViewSource x:Key="products" Source="{Binding Source={StaticResource list}, Path=Items}" Filter="productFilter"></CollectionViewSource>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="80"></RowDefinition>
<RowDefinition Height="20"></RowDefinition>
<RowDefinition Height="200"></RowDefinition>
<RowDefinition Height="50"></RowDefinition>
<RowDefinition Height="200"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<StackPanel Grid.Row="0" Grid.ColumnSpan="2" Margin="5,5,5,5">
<TextBox/>
<Button Content="ok" Margin="0,5,0,0" HorizontalAlignment="Stretch" Height="30" Width="150" Click="Button_Click"/>
</StackPanel>
<StackPanel Grid.RowSpan="2" Grid.Column="2">
<ListBox Name="orders" IsEnabled="{Binding ElementName=check, Path=IsChecked}" Margin="85,5,85,5" Height="70" ItemsSource="{Binding Source={StaticResource list}}" DisplayMemberPath="SalesOrder"/>
<CheckBox Name="check" HorizontalAlignment="Center" Content="Wybierz zamówienie" IsChecked="False"/>
</StackPanel>
<GroupBox Header="Wares" Grid.Row="2" Grid.Column="0">
<ListBox Name="lbWares" ItemsSource="{Binding Source={StaticResource wares}}" >
<ListBox.ItemTemplate>
<DataTemplate>
<!--<StackPanel Orientation="Horizontal">-->
<TextBlock Text="{Binding Path=Name}"></TextBlock>
<!--<TextBlock Text="{Binding ZaE_TwrKod}" />
<TextBlock Text=", " />
<TextBlock Text="{Binding ZaE_Ilosc}" />
<TextBlock Text=", " />
<TextBlock Text="{Binding ZaE_TwrNazwa}" />-->
<!--</StackPanel>-->
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</GroupBox>
<GroupBox Header="Materials" Grid.Row="2" Grid.Column="1">
<ListBox Name="lbMaterials" ItemsSource="{Binding Source={StaticResource materials}}">
<ListBox.ItemTemplate>
<DataTemplate>
<!--<StackPanel Orientation="Horizontal">-->
<TextBlock Text="{Binding Path=Name}"/>
<!--<TextBlock Text=", " />
<TextBlock Text="{Binding ZaE_Ilosc}" />
<TextBlock Text=", " />
<TextBlock Text="{Binding ZaE_TwrNazwa}" />-->
<!--</StackPanel>-->
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</GroupBox>
<GroupBox Header="Products" Grid.Row="2" Grid.Column="2">
<ListBox Name="lbProducts" ItemsSource="{Binding Source={StaticResource products}}">
<ListBox.ItemTemplate>
<DataTemplate>
<!--<StackPanel Orientation="Horizontal">-->
<TextBlock Text="{Binding Path=Name}"/>
<!--<TextBlock Text=", " />
<TextBlock Text="{Binding ZaE_Ilosc}" />
<TextBlock Text=", " />
<TextBlock Text="{Binding ZaE_TwrNazwa}" />
</StackPanel>-->
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</GroupBox>
</Window>
DemoList object is binding to CollectionViewList x:Key=list.
Here is my buisiness logic i need to implement:
If checkbox is marked i need to return selected ListBoxItem to the
corresponding containers [wares, products, materials] - this logic is
working
If checkbox is unmarked i need to return ALL items
[ObservableCollection] of ALL headers to the corresponding
containers [wares, products, materials]
I'm stuck right here, can anyone suggest me a solution?
--- 2013-11-04 20:38
Sry for misunderstanding, and for my bad english.
I uploaded some screen to be more clear.
http://imgur.com/UowQrRP
As you see on the screen i need to implement behavior for checkbox.
When it is unchecked each DemoItem object must be display in one of 3 containers.
Each container is bind to CollectionViewSource.
I currently have a working method, but does not work for what I need. Here's how the Settings window looks:
Right now I am binding the Department tab DataContext property to an ObservableCollection of Department objects, and then I just refer to the properties of the Department object in the text boxes to the right. Here is the code for this tab:
<TabItem Header="Department Settings"
DataContext="{Binding Departments}">
<DockPanel Margin="3,3,3,3">
<DockPanel DockPanel.Dock="Left"
Width="200">
<StackPanel DockPanel.Dock="Bottom"
Margin="0,5,0,0"
Orientation="Horizontal">
<TextBox x:Name="tbxAddDepartmentName"
Width="160"
Padding="0,5,0,5" />
<Button x:Name="btnAddDepartment"
Content="Add"
Margin="5,0,5,0"
Padding="5,5,5,5"
Command="{Binding AddDepartmentCommand, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>
<ListBox ItemsSource="{Binding}" />
</DockPanel>
<StackPanel DockPanel.Dock="Bottom">
<Button Content="Save Changes"
Padding="5,5,5,5"
HorizontalAlignment="Right" />
</StackPanel>
<Grid Margin="5">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<!-- Labels -->
<Label Grid.Row="0" Grid.Column="0">Department Name:</Label>
<Label Grid.Row="1" Grid.Column="0">Report Number:</Label>
<Label Grid.Row="2" Grid.Column="0">Address:</Label>
<!-- Input -->
<TextBox x:Name="tbxDepartmentName"
Text="{Binding Name}"
Grid.Row="0" Grid.Column="1"
VerticalContentAlignment="Center"
Margin="0,5,0,5"
Padding="5" />
<TextBox Grid.Row="1" Grid.Column="1"
Text="{Binding ReportNumber}"
VerticalContentAlignment="Center"
Margin="0,5,0,5"
Padding="5" />
<TextBox Grid.Row="2" Grid.Column="1"
Text="{Binding Address}"
VerticalContentAlignment="Center"
AcceptsReturn="True"
Margin="0,5,0,5"
Padding="5" />
</Grid>
</DockPanel>
</TabItem>
What I want to do is have a pointer to the specific Department object that is selected with the ListBox inside my ViewModel. This way, I should be able to do a one way binding on the textboxes to the right, and save change to the SQL Compact DB after I hit the "Save Changes" Button.
Sample ViewModel:
public class ViewModel : INotifyPropertyChanged, INotifyPropertyChanging
{
public class MyObj
{
public string Test1 { get; set; }
public string Test2 { get; set; }
}
#region selectedItem
private MyObj _selectedItem;
public MyObj selectedItem
{
get
{
return _selectedItem;
}
set
{
if (_selectedItem != value)
{
NotifyPropertyChanging("selectedItem");
_selectedItem = value;
NotifyPropertyChanged("selectedItem");
}
}
}
#endregion
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
// Used to notify the page that a data context property changed
protected void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
#region INotifyPropertyChanging Members
public event PropertyChangingEventHandler PropertyChanging;
// Used to notify the data context that a data context property is about to change
protected void NotifyPropertyChanging(string propertyName)
{
if (PropertyChanging != null)
{
PropertyChanging(this, new PropertyChangingEventArgs(propertyName));
}
}
#endregion
}
Add to your ListBox:
SelectedItem="{Binding selectedItem, UpdateSourceTrigger=PropertyChanged}"
Your dataContext should be whole ViewModel, not a collection.
Then you can set in listBox
ItemsSource="{Binding Departments}"
and in the Grid
DataContext="{Binding Departments}"
I have a need to use two listboxes, each bound to a different collection.
i originally had this working with one listbox and binding before the need to bind two came up.
Here is how I was doing that.
<Window x:Class="TeamManager.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:loc ="clr-namespace:TeamManager"
Title="Game Manager" Height="800" Width="800">
<Window.Resources>
<DataTemplate DataType="{x:Type loc:Game}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"></ColumnDefinition>
<ColumnDefinition Width="100"></ColumnDefinition>
<ColumnDefinition Width="100"></ColumnDefinition>
<ColumnDefinition Width="100"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Name="dateBlock" Grid.Column="0" Grid.Row="1" Text="{Binding Date, StringFormat=d}"></TextBlock>
<TextBlock Name="TimeBlock" Grid.Column="1" Grid.Row="1" Text="{Binding Time}"></TextBlock>
<Button Grid.Row="1" Grid.Column="2" CommandParameter="{Binding Id}" Click="Manage_Click" >Manage</Button>
<Button Grid.Row="1" Grid.Column="3" CommandParameter="{Binding Id}" Click="Delete_Click" Height="16" Width="16">
<Image Source="/Images/DeleteRed.png"></Image>
</Button>
</Grid>
</DataTemplate>
</Window.Resources>
<StackPanel>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
<StackPanel>
<TextBlock>Upcomming Games</TextBlock>
<ListBox ItemsSource="{Binding}" Name="GameList"></ListBox>
</StackPanel>
<StackPanel Orientation="Vertical" HorizontalAlignment="Left">
<Button Height="30" Width="100" Margin="10,10,10,10" Click="AddGame_Click">Add New Game</Button>
</StackPanel>
</StackPanel>
</StackPanel>
And my code simply set the DataContext of the window to a ObservableCollection
with the need to use TWO collections I created a wrapper class like this
public class AppModel
{
public ObservableCollection<Game> gameCollection { get; set; }
public ObservableCollection<Player> playerCollection { get; set; }
}
And my CS is now setting the DataContext to an object of AppModel
GameDBEntities _entity = new GameDBEntities();
AppModel _model;
public MainWindow()
{
InitializeComponent();
DataContext = model;
}
AppModel model
{
get
{
if (_model == null)
{
_model = new AppModel();
}
if (_model.gameCollection == null)
{
_model.gameCollection = new ObservableCollection<Game>(_entity.Games);
}
if (_model.playerCollection == null)
{
_model.playerCollection = new ObservableCollection<Player>(_entity.Players);
}
return _model;
}
set { }
}
In my Xaml, how can I set the datacontext of the existing listBox to be bound to the Collection Of Games in The AppModel?
Once I get that working I will work on the second listbox on my own.
Thanks!
You need to add a Path to the Binding. The DatacContext will be the model, the path should point to either collection:
<ListBox ItemsSource="{Binding gameCollection}" ...
Would changing the Binding to <ListBox ItemsSource="{Binding Path=gameCollection}" Name="GameList"></ListBox> solve your problem?
As per your question you state that you used to set the DataContext to the gameCollection, but now that you have changed this to use the AppModel, you will need to also change your binding as appropriate.
This will essentially change the Binding from being just bound to gameCollection, it will now be set to use AppData.gameCollection.