I'm using Syncfusion's datagrid in a UWP project. Everything works fine except command binding of button inside a GridTemplateColumn. What could be the issue ?
XAML
<my:GridTemplateColumn MappingName="Actions" HeaderText="Actions"
AllowFiltering="False">
<my:GridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Spacing="0" HorizontalAlignment="Center">
<Button VerticalAlignment="Center" Width="40" Content="Delete"
my:FocusManagerHelper.FocusedElement="True"
Command="{x:Bind ViewModel.RemoveBtnCommand}"/>
</StackPanel>
</DataTemplate>
</my:GridTemplateColumn.CellTemplate>
</my:GridTemplateColumn>
View Model
public ICommand RemoveBtnCommand { get; }
public HRMDepartmentsViewModel()
{
IsActive = true;
RemoveBtnCommand = new AsyncRelayCommand(CommandRemoveBtnClickedExecute);
}
private async Task CommandRemoveBtnClickedExecute()
{
// never executed-- code here
}
What else i've tried
I tried to use Binding instead if x:Bind but it also doesn't work
Command="{Binding Path=RemoveBtnCommand}" CommandParameter="{Binding}"
Observation
If i don't use Command and use Click event binding it works.
<my:GridTemplateColumn MappingName="Actions" HeaderText="Actions"
AllowFiltering="False">
<my:GridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Spacing="0" HorizontalAlignment="Center">
<Button VerticalAlignment="Center" Width="40" Content="Delete"
Click="{x:Bind ViewModel.ButtonBase_OnClick}"/>
</StackPanel>
</DataTemplate>
</my:GridTemplateColumn.CellTemplate>
</my:GridTemplateColumn>
View Model
public void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
// It gets called
}
TemplateColumn button command binding not working in Syncfusion DataGrid
I'm afraid you can't bind the button command in the DataTemplate like above, because command will not find correct DataContext. If you want to bind the ViewModel's RemoveBtnCommand, you need get root DataContext then direct to RemoveBtnCommand property. For more please refer the following code.
<Page.DataContext>
<local:MainViewModel x:Name="ViewModel" />
</Page.DataContext>
<Grid>
<Custom:SfDataGrid x:Name="MyDataGrid" ItemsSource="{Binding Orders}">
<Custom:SfDataGrid.Columns>
<Custom:GridTemplateColumn
AllowFiltering="False"
HeaderText="Actions"
MappingName="Actions"
>
<Custom:GridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel
HorizontalAlignment="Center"
Orientation="Horizontal"
Spacing="0"
>
<TextBlock Text="{Binding Name}" />
<Button
Width="40"
VerticalAlignment="Center"
Custom:FocusManagerHelper.FocusedElement="True"
Command="{Binding ElementName=MyDataGrid, Path=DataContext.RemoveBtnCommand}"
Content="Delete"
/>
</StackPanel>
</DataTemplate>
</Custom:GridTemplateColumn.CellTemplate>
</Custom:GridTemplateColumn>
</Custom:SfDataGrid.Columns>
</Custom:SfDataGrid>
</Grid>
You can achieve your requirement by pass the row information as a parameter to the command in ViewModel when clicking a button in TemplateColumn by passing the CommandParameter. Please refer the below KB documentation for more details reference,
KB Link:https://www.syncfusion.com/kb/5910/how-to-pass-row-data-as-parameter-to-the-command-in-viewmodel-when-clicking-the-button-in
Regards,
Vijayarasan S
I have two DockPanel elements:
<DockPanel Margin="10">
<TextBlock Text="+ Add new note" />
</DockPanel>
<DockPanel Margin="10">
<ComboBox>
<ComboBoxItem>One</ComboBoxItem>
<ComboBoxItem>Two</ComboBoxItem>
</ComboBox>
<Button Content="Add Note" DockPanel.Dock="Right" Margin="0" Padding="10,0" />
<TextBox Margin="10,0" />
</DockPanel>
I want to get follow result: once I click on first DockPanel, it must be hidden and second one is showed instead. After I click on button Add Note, second DockPanel must be hidden and first one must be appeared again.
I wonder an approach how to make it but don't know where to begin.
I'm appreciate for any suggestions.
A rough solution (no MVVM base) might be the following:
MainWindow.xaml
<Grid>
<DockPanel Margin="10" x:Name="EditDP" Visibility="Collapsed">
<ComboBox>
<ComboBoxItem>One</ComboBoxItem>
<ComboBoxItem>Two</ComboBoxItem>
</ComboBox>
<Button Content="Add Note" DockPanel.Dock="Right" Margin="0" Padding="10,0" Click="ButtonBase_OnClick"/>
<TextBox Margin="10,0" />
</DockPanel>
<DockPanel x:Name="MainDP" Margin="10" MouseLeftButtonDown="UIElement_OnMouseLeftButtonDown">
<TextBlock Text="+ Add new note" />
</DockPanel>
</Grid>
MainWindow.xaml.cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void UIElement_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
this.MainDP.Visibility = Visibility.Collapsed;
this.EditDP.Visibility = Visibility.Visible;
}
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
this.MainDP.Visibility = Visibility.Visible;
this.EditDP.Visibility = Visibility.Collapsed;
}
}
Bind the Visibility property of both the dockpanels to the same boolean and use InverseBooleanToVisibilityConverter / BooleanToVisibilityConverter on each of them.
This way when you flip the boolean using either the click event on the first Dock panel or the button click on the second panel, the two panels will alternatively show up
I have some code in the view:
<StackPanel Orientation="Horizontal" Background="{StaticResource GrayBrush8}">
<RadioButton Content="Radio1" />
<RadioButton Content="Radio2" />
</StackPanel>
<ct:DynamicFilterPanel Grid.Row="1"
ItemsType="{x:Type db:RadioData1}"
DbContext="{Binding DataContext}"
FilterQuery="{Binding FilterQuery, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
ChildCollectionsFilters="{Binding SubTypesFilter}"
WindowType="{x:Type mah:MetroWindow}"
/>
<ct:BDataGrid Grid.Row="2" IsReadOnly="True" ItemsSource="{Binding Model.List}" SelectedItem="{Binding Model.SelectedItem}" />
And I have some class with data and name of columns, models and viewmodels.
When I start the app it shows columns with data of RadioData1. Ok. And the first radiobutton is for that. But how can I do when I click second radio button it shows another list with columns from RadioData2. What kind of converter? Or changes I have to make in this view.
you must edit XAML
<StackPanel Orientation="Horizontal" Background="{StaticResource GrayBrush8}">
<RadioButton Name="Radio1" Content="Radio1" DataContextChanged="RadioButton_DataContextChanged" />
<RadioButton Name="Radio2" Content="Radio2" />
</StackPanel>
and in CS File
add method
private void RadioButton_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if (Radio1.IsChecked==true)
{
//your Code
}
else
{
//your other code
}
}
and u can Use visibility for show or hide Something in XAML
<Button Name="btn1" Visibility="Hidden" />
and Use in your CS file like this
if (Radio1.IsChecked==true)
{
btn1.Visibility = Visibility.Visible;
}
I have a DataGridTemplateColumn whose header basically consists of StackPanel which contains a Button and TextBlock. I would want to access the Cell content or DataGridCell when the datagridrow is loaded.
My one of the datagridcolumn looks like this:
<DataGridTemplateColumn>
<DataGridTemplateColumn.HeaderTemplate >
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Button Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}" Click="HeaderButtonClick">
<Button.Content>
<Path Stretch="Fill" Fill="Black" Stroke="{x:Null}" StrokeThickness="0.5"
Data="M3.875,0 L5.125,0 5.125,3.875 9,3.875 9,5.125 5.125,5.125 5.125,9 3.875,9 3.875,5.125 0,5.125 0,3.875 3.875,3.875 3.875,0 z" />
</Button.Content>
</Button>
<TextBlock Text="Fund" Margin="20,0,0,0"/>
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.HeaderTemplate>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Fund}" Margin="20,0,0,0"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
and the datagrid_loadingrow event looks like
var dg = sender as DataGrid;
if (dg != null)
{
foreach (var item in dg.Columns)
{
DataGridCell cell1 = item.GetCellContent(row) as DataGridCell;
}
}
Can anyone help me with this?
This is WPF, not WindowsForms. When using WPF, we data bind to UI control properties, rather than attempting to programmatically set these values. When data binding, you already have access to the data in your code behind/view model, so there really is no need to attempt to access it from the UI controls.
If you look at the DataGridTemplateColumn Class page on MSDN, you'll see this example:
<Grid>
<Grid.Resources>
<!--DataTemplate for Published Date column defined in Grid.Resources. PublishDate is a property on the ItemsSource of type DateTime -->
<DataTemplate x:Key="DateTemplate" >
<StackPanel Width="20" Height="30">
<Border Background="LightBlue" BorderBrush="Black" BorderThickness="1">
<TextBlock Text="{Binding PublishDate, StringFormat={}{0:MMM}}" FontSize="8" HorizontalAlignment="Center" />
</Border>
<Border Background="White" BorderBrush="Black" BorderThickness="1">
<TextBlock Text="{Binding PublishDate, StringFormat={}{0:yyyy}}" FontSize="8" FontWeight="Bold" HorizontalAlignment="Center" />
</Border>
</StackPanel>
</DataTemplate>
<!--DataTemplate for the Published Date column when in edit mode. -->
<DataTemplate x:Key="EditingDateTemplate">
<DatePicker SelectedDate="{Binding PublishDate}" />
</DataTemplate>
</Grid.Resources>
<DataGrid Name="DG1" ItemsSource="{Binding}" AutoGenerateColumns="False" >
<DataGrid.Columns>
<!--Custom column that shows the published date-->
<DataGridTemplateColumn Header="Publish Date" CellTemplate="{StaticResource DateTemplate}" CellEditingTemplate="{StaticResource EditingDateTemplate}" />
</DataGrid.Columns>
</DataGrid>
</Grid>
Notice the Bindings... for example, we can see this:
<DatePicker SelectedDate="{Binding PublishDate}" />
This value can be accessed directly from the PublishDate property of the data bound object, rather than from the DataGrid:
DateTime publishDate = DataBoundCollection.ElementAt(relevantRowIndex).PublishDate;
You can find out more about data binding from the Data Binding Overview page on MSDN.
Here is answer.How you would access template column content using code.If you want to access any type of Control content e.g Button content ,TextBlock content etc.Then you create load event for those Controls.Then go to load event code.In load event you would be access Content of those Controls.
I am going to access the Button child of Stack Panel.
So follow this code.
Xaml:
<DataGridTemplateColumn>
<DataGridTemplateColumn.HeaderTemplate >
<DataTemplate>
<StackPanel Orientation="Horizontal" Loaded="StackPanel_Loaded">
<Button Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}" Click="HeaderButtonClick">
<Button.Content>
<Path Stretch="Fill" Fill="Black" Stroke="{x:Null}" StrokeThickness="0.5"
Data="M3.875,0 L5.125,0 5.125,3.875 9,3.875 9,5.125 5.125,5.125 5.125,9 3.875,9 3.875,5.125 0,5.125 0,3.875 3.875,3.875 3.875,0 z" />
</Button.Content>
</Button>
<TextBlock Text="Fund" Margin="20,0,0,0"/>
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.HeaderTemplate>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Fund}" Margin="20,0,0,0"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
Code Behind .cs
private void StackPanel_Loaded(object sender, RoutedEventArgs e)
{
StackPanel stack = sender as StackPanel;
Button button = stack.Children.OfType<Button>().FirstOrDefault();
button.Content = "Change Content";
}
In my situation I want to access button in Template Column.I used this code
XAML
<DataGridTemplateColumn x:Name="deleteDG" Header="Delete" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate x:Uid="deletetemp" >
<Button Click="deleteBtn_Click" Loaded="Button_Loaded" Width="95" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" Background="White" Content="Delete"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
Code Behind .cs
private void Button_Loaded(object sender, RoutedEventArgs e)
{
Button button = sender as Button;
button.Content = "Change COntent";
}
I have this XAML
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<StackPanel>
<Button Content="Reply" Name="btnReply" Click="btnReply_Click" HorizontalAlignment="Left" Margin="5" Padding="10,0" />
<Label Content="{Binding Path=Subject}" FontWeight="Bold" />
<Label Content="{Binding Path=Body}" />
</StackPanel>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
DataGrid bound to List
inside btnReply_Click I'd like to get instance of MyObject
How do I do this?
var myObject = (sender as FrameworkElement).DataContext as MyObject;
Since the DataContext is inherited.