Binding a command in a datagrid - wpf

I am trying to bind a button withing datagrid to a custom command.
But for some reason, the command dont get executed.
This is the XAML:
<Grid Name="LayoutRoot">
<ListView Name="ListView1"
ItemsSource="{Binding}"
IsSynchronizedWithCurrentItem="True">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
<ListView.View>
<GridView>
<GridViewColumn Header="ID" Width="100">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding Path=id,Mode=OneWay}"
Margin="-6,0,-6,0" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Name" Width="100">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding Path=name,Mode=OneWay}"
Margin="-6,0,-6,0" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Path" Width="50">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding Path=path,Mode=OneWay}"
Margin="-6,0,-6,0" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Update" Width="50">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Button CommandParameter="{Binding id}" Command="{Binding ???????????}" Content="Edit"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
</Grid>
</Window>
What should I write instead of the ?????????? in order to show a message with the ID.
Found a solution here:
WPF DataGrid - Button in a column, getting the row from which it came on the Click event handler

I think problem is in Cells DataContext. Within DataTemplate it does not see parent context. Try to add your command to Resources and do something like:
<DataTemplate>
<Button CommandParameter="{Binding id}" Command="{StaticResource yourCommand}" Content="Edit"/>
</DataTemplate>

Create a command Inherit from ICommand interface.
public class ShowMessageWithIdCommand : ICommand
{
// Implement it members
}
in your viewmodel:
public ICommand ShowMessageWithIdCommand
{
get{return new ShowMessageWithIdCommand(...);}
}
Then your ????? will be: ShowMessageWithIdCommand
More detail you can find here: http://msdn.microsoft.com/en-us/magazine/dd419663.aspx

Related

Getting user input from listview

I created a listview. I need to get the user's input from the Textbox inside the listview. When user click on submit button User input from listview are displayed in a MessageBox. How to get user input from textbox inside the listview
<ListView x:Name="lstvQualification"
Height="96"
Margin="10,6,14,0"
VerticalAlignment="Top">
<ListView.View>
<GridView>
<GridViewColumn Width="249" Header="Education">
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBox x:Name="txtEducation"
Width="247"
Text="{Binding education}" />
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Width="253" Header="College/Institution">
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBox x:Name="txtCollege"
Width="251"
Text="{Binding college}" />
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Width="88" Header="Mark(%)">
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBox x:Name="txtMark"
Width="86"
Text="{Binding mark}" />
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Width="88" Header="Add">
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Button x:Name="btnAddQualification"
Click="btnAddQualification_Click"
Content="Add"
Style="{StaticResource NewImg}" />
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
<Button Content="Submit" x:name="submit" />
This could be the example for change in your code to work fine:
<ListView x:Name="myListView"
HorizontalAlignment="Stretch"
ItemsSource="{Binding Source={StaticResource myCollectionViewSource},XPath='Party',Mode=TwoWay}">
<ListView.View>
<GridView>
<GridViewColumn Width="100" DisplayMemberBinding="{Binding XPath='Contact'}" Header="Contact"/>
<GridViewColumn DisplayMemberBinding="{Binding XPath='Qty'}" Header="Q"/>
<GridViewColumn DisplayMemberBinding="{Binding XPath='Amount'}" Header="Amt"/>
<GridViewColumn x:Name="tbTot" Header="Tot">
<GridViewColumn.CellTemplate>
<DataTemplate>
<DockPanel>
<TextBox LostFocus="TextBox_LostFocus" Width="100" Text="{Binding XPath='Text'}" />
</DockPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
You already use {Binding ...} everywhere in the cell templates, those bindings are TwoWay by default, so any user input would/should automatically be passed to underlying data objects. However, I don't see any binding on ListView.ItemsSource property, so most probably you forgot to prepare the dataobjects. Create a collection of dataitems, bind them to the ItemsSource, let the ListView display them and celltemplates with bindings should update the dataitems' properties with no extra work from your side. When submit is pressed, just check the collection of dataitems, all the data entered should be already there (assuming you made all models and bindings properly).

How to bind button inside listview

I cant bind button inside listview to the GoToTask property, every other binding, include second button in the grid is work well.
<Grid>
<ListView ItemsSource="{Binding Projects}" SelectedItem="{Binding SelectedProject, Mode=TwoWay}" Grid.Row="1">
<ListView.Resources>
<Style TargetType="{x:Type GridViewColumnHeader}">
<Setter Property="Visibility" Value="Collapsed"/>
</Style>
</ListView.Resources>
<ListView.View>
<GridView>
<GridViewColumn DisplayMemberBinding="{Binding Name}"/>
<GridViewColumn Header="Go">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Button Content="Go" Command="{Binding Path=GoToTasks, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
<Button Height="20" Width="50" HorizontalAlignment="Right" Command="{Binding GoToTasks}" Content="Go"/>
</Grid>
Everything is inside UserControl.
What is wrong?
GridViewColumn is not part of VisualTree and therefore you are not allowed to use FindAncestor.
Similar here. Try ElementName, as far as I remember it uses LogicalTree.

How to set ListView selection from the template element that has focus?

I have a ListView that uses data templates to display specific controls within the cells:
<ListView Grid.Row="1" ItemsSource="{Binding Ratings}" SelectedItem="{Binding SelectedRating}" Margin="5" MinHeight="50" SelectionMode="Single" ScrollViewer.CanContentScroll="True"
local:GridViewSort.Enable="True">
<ListView.View>
<GridView>
<GridViewColumn Header="Date" local:GridViewSort.PropertyName="RatingDate">
<GridViewColumn.CellTemplate>
<DataTemplate>
<DatePicker SelectedDate="{Binding RatingDate}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Rating ID" local:GridViewSort.PropertyName="RatingID">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding RatingID}" Width="35" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Name" local:GridViewSort.PropertyName="RatingName">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding RatingName}" Width="35" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Age" local:GridViewSort.PropertyName="RatingAge">
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBox Text="{Binding RatingAge}" Width="35" />
<TextBlock Text=" yrs"/>
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
I also have a delete button to remove the selected row.
My user has a habit of clicking into to the edit and date controls (which doesn't change the selected row) and then hitting delete to remove the row he has clicked on. Unfortunately, this deletes the wrong row.
How can I change the row selection whenever the user clicks into the controls?
You can use PreviewMouseUp event on a ListViewItem:
<ListView Grid.Row="1" ItemsSource="{Binding Ratings}" SelectedItem="{Binding SelectedRating}" Margin="5" MinHeight="50" SelectionMode="Single" ScrollViewer.CanContentScroll="True"
local:GridViewSort.Enable="True">
<ListView.Resources>
<Style TargetType="{x:Type ListViewItem}">
<EventSetter Event="PreviewMouseUp" Handler="ListViewItem_PreviewMouseUp" />
</Style>
</ListView.Resources>
<ListView.View>
<GridView>
...
Code behind:
private void ListViewItem_PreviewMouseUp(object sender, MouseButtonEventArgs e)
{
var listViewItem = sender as ListViewItem;
if (listViewItem != null)
{
listViewItem.IsSelected = true;
}
}

WPF GridView shared cell template for all columns

I am trying to create a DataTemplate that can be shared for all columns of a GridView, which has it's columns created dynamically (through code-behind).
I would like to create the DataTemplate as a resource in XAML instead of entirely in code-behind, but I can't figure out how to get the bindings to work properly.
The following is the closest I could come up with (but does not work):
<DataTemplate x:Key="ListViewCellTemplate">
<TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type GridViewColumn}}}" />
</DataTemplate>
This template is assigned as the CellTemplate of each column as follows:
BindableDataTable table = this.DataContext as BindableDataTable;
foreach (BindableDataColumn c in table.Columns)
{
GridViewColumn col = new GridViewColumn();
col.Header = c.ColumnName;
col.CellTemplate = this.FindResource("ListViewCellTemplate") as DataTemplate;
v.Columns.Add(col);
}
Answer:
Set a DataTemplate in your resources
<UserControl.Resources>
<ResourceDictionary>
<DataTemplate x:Key="GridViewCellTemplateStyle">
<TextBlock Text="{Binding}">
<TextBlock.InputBindings>
<MouseBinding Gesture="LeftDoubleClick" Command="{Binding DataContext.CommandDoubleClick, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListView}}}"/>
</TextBlock.InputBindings>
</TextBlock>
</DataTemplate>
</ResourceDictionary>
</UserControl.Resources>
Create your grid view and make the columns inherit this datatemplate
<ListView>
<ListView.View>
<GridView>
<GridViewColumn Width="Auto" Header="Column1" CellTemplate="{StaticResource GridViewCellTemplateStyle}"/>
<GridViewColumn Width="Auto" Header="Column2" CellTemplate="{StaticResource GridViewCellTemplateStyle}"/>
<GridViewColumn Width="Auto" Header="Column3" CellTemplate="{StaticResource GridViewCellTemplateStyle}"/>
<GridViewColumn Width="Auto" Header="Column4" CellTemplate="{StaticResource GridViewCellTemplateStyle}"/>
</GridView>
</ListView.View>
</ListView>
This exmaple shows you how to create a double clickable row in a GridViewColumn.
Just change the DataTemplate as you see fit
I'm having the exact same problem.
I want to be able to apply the data template to different columns but have each column bound to a separate data field.
<ListView ItemsSource="{Binding}" Name="listViewIMS" Grid.Row="1" Margin="0,0,0,4" FontSize="11" AlternationCount="2" SelectionMode="Extended">
<ListView.Resources>
<DataTemplate x:Key="Templ">
<TextBlock TextAlignment="Left" Text="{Binding}"/>
</DataTemplate>
<DataTemplate x:Key="Tempr">
<TextBlock Width="78" Margin="-6,0" TextAlignment="Right" Text="{Binding}" />
</DataTemplate>
<Style x:Key="HeaderStyleRight" TargetType="GridViewColumnHeader">
<Setter Property="HorizontalContentAlignment" Value="Right"/>
</Style>
<Style x:Key="HeaderStyleLeft" TargetType="GridViewColumnHeader">
<Setter Property="HorizontalContentAlignment" Value="Left"/>
</Style>
</ListView.Resources>
<ListView.View>
<GridView x:Name="gridViewInvoices">
<GridViewColumn Width="80" DisplayMemberBinding="{Binding Document}">
<GridViewColumnHeader Tag="docNo" Content="Document" />
</GridViewColumn>
<GridViewColumn Width="220" DisplayMemberBinding="{Binding Customer}">
<GridViewColumnHeader Tag="customer" Content="Customer"/>
</GridViewColumn>
<GridViewColumn Width="100" DisplayMemberBinding="{Binding inv_date, StringFormat='dd/MM/yy'}" >
<GridViewColumnHeader Tag="date" Content="Date" />
</GridViewColumn>
<GridViewColumn Width="100" DisplayMemberBinding="{Binding inv_l_catalogue}" >
<GridViewColumnHeader Tag="catalogue" Content="Item" />
</GridViewColumn>
<GridViewColumn Width="60" DisplayMemberBinding="{Binding inv_l_qty}" >
<GridViewColumnHeader Tag="qty" Content="Qty" />
</GridViewColumn>
<GridViewColumn Width="80" DisplayMemberBinding="{Binding inv_l_price, StringFormat='0.00' }" >
<GridViewColumnHeader Tag="unitPrice" Content="Price" />
</GridViewColumn>
<GridViewColumn Width="50" DisplayMemberBinding="{Binding inv_l_per}" >
<GridViewColumnHeader Tag="per" Content="Per" />
</GridViewColumn>
<GridViewColumn Header="Goods" CellTemplate ="{StaticResource Tempr}" HeaderContainerStyle="{StaticResource HeaderStyleRight}" Width="80" >
<!--GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Width="78" Margin="-6,0" TextAlignment="Right" Text="{Binding inv_l_lgoods2, StringFormat='0.00'}" />
</DataTemplate>
</GridViewColumn.CellTemplate>-->
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
#jonathan-beresford
This question is old... But, for future reference:
You can binding on the template
<DataTemplate x:Key="Templ">
<TextBlock TextAlignment="Left" Text="{Binding inv_l_catalogue}"/>
</DataTemplate>

WPF ListView with GridViewColumn and DataTemplate

I have a CheckedListBox control which is created by adding a DataTemplate with a CheckBox to a ListView. The problem is that I need columns too.
The following code doesn't display the check boxes:
<ListView x:Name="lbDatabases" Height="138" Width="498" Canvas.Left="44" Canvas.Top="146">
<ListView.View>
<GridView>
<GridViewColumn DisplayMemberBinding="{Binding DbName}" Header="Databases" Width="498"/>
</GridView>
</ListView.View>
<ListView.ItemTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsActive}" Checked="AnyChange" Unchecked="AnyChange" Style="{x:Null}" Content="{Binding DbName}"
Width="{Binding CheckWidth}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
However, if I comment out this code, everything works fine but no columns:
<ListView.View>
<GridView >
<GridViewColumn DisplayMemberBinding="{Binding DbName}" Header="Databases" Width="498"/>
</GridView>
</ListView.View>
Is there any way to have it all?
You need to define the data template as CellTemplate for your column:
<ListView x:Name="lbDatabases" Height="138" Width="498" Canvas.Left="44" Canvas.Top="146" >
<ListView.View >
<GridView >
<GridViewColumn Header="Databases" Width="498">
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsActive}" Checked="AnyChange" Unchecked="AnyChange" Style="{x:Null}" Content="{Binding DbName}"
Width="{Binding CheckWidth}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
ok after struggling all morning I figured it out. They key here is to use a CellTemplate:
<ListView x:Name="lbDatabases" Height="138" Width="498" Canvas.Left="44" Canvas.Top="146" Style="{StaticResource ListViewStyle}">
<ListView.View >
<GridView>
<GridViewColumn Header="Databases" Width="498">
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsActive}" Checked="AnyChange" Unchecked="AnyChange" Style="{x:Null}" Content="{Binding DbName}"
Width="{Binding CheckWidth}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>

Resources