Button-Command in einem DataGridTemplateColumn.Header
-
Donnerstag, 9. August 2012 05:48
Hallo,
Wie kann ich es hinbekomme in einem DataGrid (DataGridTemplateColumn.Header) ein Command Binding hinzubekommen. Bei einem Button außerhalb des DataGrid funktioniert es, wenn ich aber ein Button im Grid-Header habe geht es nicht. Es kommt der Hinweis das das Property nicht gefunden wird. Das muß doch aber gehen.
Danke und Gruß
Gerhard Ahrens- Bearbeitet Robert BreitenhoferMicrosoft Contingent Staff, Moderator Donnerstag, 16. August 2012 16:14 Formatierung
Alle Antworten
-
Donnerstag, 9. August 2012 07:28
Hi Gerhard,da es bei mir problemlos funktioniert, wird bei Dir vermutlich eine falsche Bindung vorliegen. Hier meine Demo:<Window x:Class="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:local="clr-namespace:WpfApplication1"> <Window.Resources> <local:ViewModel x:Key="vm"/> </Window.Resources> <StackPanel DataContext="{Binding Source={StaticResource vm}}"> <DataGrid Name="dg" ItemsSource="{Binding View}" AutoGenerateColumns="False"> <DataGrid.Columns> <DataGridTextColumn Binding="{Binding col1}" SortMemberPath=""> <DataGridTextColumn.HeaderTemplate> <DataTemplate> <Button Content="Kopf" Command="{Binding Source={StaticResource vm}, Path=cmd}"/> </DataTemplate> </DataGridTextColumn.HeaderTemplate> </DataGridTextColumn> </DataGrid.Columns> </DataGrid> <Label Content="{Binding Prop2}"/> </StackPanel> </Window>
Imports System.Data Imports System.ComponentModel Public Class ViewModel Implements INotifyPropertyChanged Dim cvs As New CollectionViewSource Public ReadOnly Property View As ICollectionView Get If cvs.View Is Nothing Then Dim dt As New DataTable With dt With .Columns With .Add("ID", GetType(Integer)) .AutoIncrement = True .AutoIncrementSeed = 1 .AutoIncrementStep = 1 End With .Add("col1", GetType(String)) End With For i = 1 To 10 Dim r = .NewRow r(1) = String.Format("Zeile {0:00}", i) .Rows.Add(r) Next End With cvs.Source = dt End If Return cvs.View End Get End Property Private cmd2 As New Action(Of Object)(AddressOf Cmd2Exec) Public ReadOnly Property cmd() As ICommand Get Return New RelayCommand(cmd2) End Get End Property Sub Cmd2Exec(ByVal obj As Object) Prop2 = String.Format("Button gedrückt: {0:HH:mm:ss.fff}", Now) End Sub Private _prop2 As String = "Button nicht gedrückt" Public Property Prop2() As String Get Return Me._prop2 End Get Set(ByVal value As String) Me._prop2 = value RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("Prop2")) End Set End Property Public Event PropertyChanged(sender As Object, e As PropertyChangedEventArgs) Implements INotifyPropertyChanged.PropertyChanged End Class Public Class RelayCommand Implements ICommand Private ReadOnly _execute As Action(Of Object) Private ReadOnly _canExecute As Predicate(Of Object) Public Sub New(ByVal execute As Action(Of Object)) Me.New(execute, Nothing) End Sub Public Sub New(ByVal execute As Action(Of Object), ByVal canExecute As Predicate(Of Object)) If execute Is Nothing Then Throw New ArgumentNullException("execute") End If Me._execute = execute Me._canExecute = canExecute End Sub <DebuggerStepThrough()> _ Public Function CanExecute(ByVal parameter As Object) As Boolean Implements ICommand.CanExecute Return If(Me._canExecute Is Nothing, True, Me._canExecute(parameter)) End Function Public Custom Event CanExecuteChanged As EventHandler Implements ICommand.CanExecuteChanged AddHandler(ByVal value As EventHandler) AddHandler CommandManager.RequerySuggested, value End AddHandler RemoveHandler(ByVal value As EventHandler) RemoveHandler CommandManager.RequerySuggested, value End RemoveHandler RaiseEvent(ByVal sender As System.Object, ByVal e As System.EventArgs) End RaiseEvent End Event Public Sub Execute(ByVal parameter As Object) Implements ICommand.Execute Me._execute(parameter) End Sub End Class--
Viele Gruesse
PeterErgänzung:
Da nntp die Bilder nicht anzeigt, sehe ich erst jetzt das Bild in Deiner Frage. "btnSort" fehlt bei Dir in dem als ItemsSource gebundenen Objekt.
- Bearbeitet Peter FleischerMVP Donnerstag, 9. August 2012 07:40 Ergänzung
- Als Antwort vorgeschlagen Peter FleischerMVP Donnerstag, 9. August 2012 07:40
- Als Antwort markiert Robert BreitenhoferMicrosoft Contingent Staff, Moderator Donnerstag, 16. August 2012 16:13
-
Freitag, 10. August 2012 05:15
Hallo Peter,
da muß ich nochmal schauen was ich falsch gemacht haben.
Danke und Gruß
Gerhard Ahrens
-
Freitag, 10. August 2012 05:37
Hallo Peter,
es funktioniert tatsächlich so. Nachdem das Grid einen DataContext bekommen hat, funktionierte der Button im Header sofort. Verstehen tue ich allerdings nicht, warum ich bei dem Grid den DataContext angeben muß,
<Grid DataContext="{Binding Source={StaticResource vm}}" Visibility="{Binding Path=VokabelDataView.IsEmpty, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource visibilityConverter}}"> <Grid.RowDefinitions> <RowDefinition Height="*" /> <RowDefinition Height="35" /> </Grid.RowDefinitions> <DataGrid Name="dataGrid1" Margin="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" AlternatingRowBackground="Gainsboro" AlternationCount="2" AutoGenerateColumns="False" CanUserAddRows="True" CanUserDeleteRows="True" commands:Behaviors.DoubleClick="{Binding EditVokabelCommand}" IsReadOnly="True" IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding Path=VokabelDataView, Mode=OneWay}" SelectionMode="Single" SelectionUnit="FullRow"> <DataGrid.Columns> <DataGridTemplateColumn Width="375" CanUserSort="True" IsReadOnly="True" SortMemberPath="txtVokabelEn"> <DataGridTemplateColumn.Header> <Grid Width="Auto" Height="Auto"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="22" /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="20" /> <RowDefinition Height="20" /> </Grid.RowDefinitions> <TextBlock Grid.Row="0" Grid.Column="0" Width="350" HorizontalAlignment="Left" Text="Vokabel Englisch" /> <Image Grid.Row="0" Grid.Column="1" Width="Auto" Height="Auto" HorizontalAlignment="Right" Source="{StaticResource imgEnGb}" Stretch="None" /> <Button x:Name="btnZweite" Grid.Row="1" Grid.Column="0" Width="Auto" Command="{Binding Source={StaticResource vm}, Path=RefreshCommand}" Content="Zweite Zeile" /> </Grid> </DataGridTemplateColumn.Header>und bei einem Botton in einem Dialog geht das auch ohne.
<Button x:Name="cmbRefreshCommand" Width="25" Height="25" Margin="5" HorizontalAlignment="Left" VerticalAlignment="Center" Command="{Binding Path=RefreshCommand}" DockPanel.Dock="Right"> <Button.ToolTip> <ToolTip Background="LightYellow"> <StackPanel> <TextBlock FontWeight="Bold">Refresh</TextBlock> <TextBlock>Liste der Vokabeln aktualisieren.</TextBlock> </StackPanel> </ToolTip> </Button.ToolTip> <Image Width="16" Height="16" Source="{StaticResource imgRefresh16}" Stretch="None" /> </Button>Gruß
Gerhard Ahrens -
Freitag, 10. August 2012 07:02Hallo Gerhard,das Grid braucht keinen DataContext. Der wird nur benötigt, wenn eingebettete Elemente den DataContext benötigen und ihnen selbst kein DataContext zugewiesen wurde. Wichtig in Deinem Beispiel bezüglich der Ausgangsfrage ist, dass als Source auch die richtige Instanz genutzt wird. Das hast Du mit der Source-Eigenschaft gemacht. Bei Deinem Button in einem Dialog fehlt die Source-Eigenschaft und er greift auf den DataContext zurück. Dieser muss aber im Baum irgendwo oberhalb auffindbar sein, bei Dir z.B. im Grid.--
Viele Gruesse
Peter

