How to bind a ICommand into a Button out of DataContext? - wpf

i have a Button into a DataGrid with a DataContext (KeyValuePair).
I want to implementing a Command into this Button.
But if i use the Command="{Binding CommandoTest}" it didnt work.
I tested the ICommand into a Grid without DataContext and it works well.
<DataGrid DataContext="{Binding PersonList.Keys}">
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Grid>
<Button Command="{Binding CommandoTest}" Content="CommandoTest"></Button>
</Grid>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
The Command Code:
Public ReadOnly Property CommandoTest As ICommand
Get
Return CommandTest_exp
End Get
End Property
Public Sub CommandTest_exp()
MessageBox.Show("Test", "Test")
End Sub

I imagine that the DataGrid is inside of some element whose DataContext is the one with the CommandoTest property on it.
If that is the case, using the example of a Grid as the parent, you could use:
<Grid x:Name="parent_grid">
<DataGrid DataContext="{Binding PersonList.Keys}">
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Grid>
<Button Command="{Binding DataContext.CommandoTest, ElementName=parent_grid}" Content="CommandoTest"></Button>
</Grid>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
Another approach, in which you don't have to name any controls, would be (this wouldn't work for the Grid in the previous example, as it would first find the Grid which is the parent of your Button, so I've added another parent element of type Border):
<Border>
<Grid>
<DataGrid DataContext="{Binding PersonList.Keys}">
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Grid>
<Button Command="{Binding DataContext.CommandoTest, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Border}}}" Content="CommandoTest"></Button>
</Grid>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Border>

Related

WPF Datagrid MouseBinding MVVM

I managed to handle a double click on one of my datagrid rows to execute a command on my viewmodel by this xaml:
This works perfect when I click somewhere in the area of the first column (which is bound to the readonly ID), but fails when the double click is done in the area of the textbox in column two (CustomerNumber, which of course catches the doubleclick).
Which would be a MVVM-like way to handle doubleclicks for both scenarios?
You could replace the DataGridTextColumn with a DataGridTemplateColumn and add a MouseBinding to the TextBox in the CellEditingTemplate:
<DataGridTemplateColumn Header="Customer Number">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding CustomerNumber}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<TextBox Text="{Binding CustomerNumber}">
<TextBox.InputBindings>
<MouseBinding Gesture="LeftDoubleClick"
Command="{Binding DataContext.EditCommand, RelativeSource={RelativeSource AncestorType=DataGrid}}" />
</TextBox.InputBindings>
</TextBox>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>

WPF - Binding a list of a string to a column in Data Grid

I have a datagrid with three columns.
<DataGrid IemSource={Binding SomeData}>
<DataGrid.Columns>
<DataGridTemplateColumn>
</DataGridTemplateColumn>
<DataGridTemplateColumn>
</DataGridTemplateColumn>
<DataGridTemplateColumn>
<DataGridTemplateColumn.HeaderTemplate>
<DataTemplate>
<ItemsControl ItemSource="{Binding SomeList}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="SomeTopic"/>
<ComboBox ItemSource="{Binding }"/>
</StackPanel>
</ItemsControl>
</DataTemplate>
</DataGridTemplateColumn.HeaderTemplate>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
SomeData is a object collection of ClassA. Class A contains two string fields and I have binded them to the first 2 columns.
The class contains a List of string variables of which the name is SomeList. I have binded it to the 3rd column. I need to attach it to the combobox in the header of column 3. But this code does not give me what I want.
can someone help ?
Your problem seems to be that you add the StackPanel as item to the ItemsControl instead of using it in a DataTemplate.
Instead of
<ItemsControl ItemSource="{Binding SomeList}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="SomeTopic"/>
<ComboBox ItemSource="{Binding }"/>
</StackPanel>
</ItemsControl>
it should look like this:
<ItemsControl ItemSource="{Binding SomeList}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="SomeTopic"/>
<ComboBox ItemSource="{Binding }"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>

how to bind the selected item from the combobox to textblock inside datagrid

I am having combobox inside datagrid which is inside cell editing template.
What i want is that when a user select an item from the combobox and move to the next cell, the selected item must bind to the textblock of that same cell.
if anyone knows how to do help me. here is my xaml
<DataGrid AutoGenerateColumns="False" VirtualizingStackPanel.IsVirtualizing="False"
Grid.Row="1" Grid.ColumnSpan="7" Name="attendancegrid" Background="#FFDCE8EB" CanUserAddRows="False"
BorderBrush="Chocolate" BorderThickness="5" RowHeight="30" IsSynchronizedWithCurrentItem="True"
HorizontalGridLinesBrush="#FFB74646" IsReadOnly="False" Foreground="Black" Loaded="attendancegrid_Loaded"
SelectionChanged="attendancegrid_SelectionChanged" CurrentCellChanged="attendancegrid_CurrentCellChanged"
CellEditEnding="attendancegrid_CellEditEnding">
<DataGridTemplateColumn Header="Monday" Width="100">
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<ComboBox x:Name="monday" Width="50" IsSynchronizedWithCurrentItem="true" Loaded="monday_Loaded" SelectionChanged="monday_SelectionChanged"></ComboBox>
<ComboBox x:Name="staff" Width="50" Loaded="staff_Loaded"></ComboBox>
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel >
<TextBlock x:Name="mon"></TextBlock>
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid>
You have to create one collection property to be bound on Combobox like
public List<string> MyCollection{get;set;}
and one string property for binding it to the SelectedItem of ComboBox and Your TextBlock like
private string _SelectedCollectionItem;
public string SelectedCollectionItem
{
get{return _SelectedCollectionItem;}
set{_SelectedCollectionItem=value;
RaisePropertyChanged("SelectedCollectionItem");}
}
now in your xaml do like this
DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<ComboBox ItemsSource="{Binding MyCollection}" SelectedItem={Binding SelectedCollectionItem,Mode=TwoWay}></ComboBox>
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel >
<TextBlock Text={Binding SelectedCollectionItem}></TextBlock>
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>

WPF Datagrid TemplateColumn Control Enable and Disable

I have Datagrid with two TemplateColumn.
First column is a Combobox and Second column with Extended IntergerUpDown control
I need to Enable/Disable the IntegerUpDown control based on the Combox box SelectedItem value.
Please help me how to accomplish this. Sample xaml below.
<Grid><DataGrid ItemsSource="{Binding List1}" Name="x1">
<DataGrid.Columns>
<DataGridTemplateColumn Header="ColorTemplate">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding DataContext.List2, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGrid}}}"
DisplayMemberPath="Name" SelectedValue="{Binding ColourId}" SelectedValuePath="Id" Tag="{Binding Id}"
HorizontalAlignment="Stretch" x:Name="discussTemplate" VerticalAlignment="Stretch"
/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="UPDown" Width="Auto">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<extToolkit:IntegerUpDown AllowSpin="True" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Width="Auto" Minimum="0"
x:Name="updown"
IsEnabled="????" >
</extToolkit:IntegerUpDown>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
This can be easily done with a DataTrigger on your ViewModel ColourId property.
As your SelectedValue property on the ComboBox is already binded, you can have a DataTrigger on your extToolkit:IntegerUpDown control that will set IsEnabled to True/False based on ColourId value on your ViewModel.

ComboBox not binding in datagrid

I have a ComboBox binded to BindingList with strings. It is working fine.
public BindingList<string> MyList
{
get
{
BindingList<string> list = new BindingList<string>();
list.Add("one");
list.Add("two");
list.Add("three");
return list;
}
}
xaml:
<ComboBox x:Name="MyCmbBox" ItemsSource="{Binding Path=MyList}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
When I same code put into the WPF 4 datagrid, it's not working any more (but the combo outside datagrid is still running ok):
<DataGrid AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox x:Name="MyCmbBox" ItemsSource="{Binding Path=MyList}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
Why? Thank you
Because in case of DataGrid the ComboBox has different DataContext - the grid row data item, which doesn't have the MyList property.
To fix this, you can use RelativeSource binding to bind to the DataContext of the grid:
<DataGrid AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox x:Name="MyCmbBox" ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}, Path=DataContext.MyList}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>

Resources