I am working on UI automation of WPF application for which i am using Micrososft Automation UI tool for automation. I have one situation where i need to click on hyperlink which is inside first column of Data grid in WPF.
below is My Ui code:
<DataGridTemplateColumn Header="Load Data" Width="85" Visibility="{Binding DataContext.IsLoaded, Source={StaticResource ProxyElement}}" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Width="15" Height="15" VerticalAlignment="Top" Cursor="Hand" Source="/Dummy.Dashboard;component/Images/Load.png" MouseDown="OnHyperlinkClick"/>
<TextBlock>
<Hyperlink Click="OnHyperlinkClick" x:Uid="TemplateLoadLink">
Template
</Hyperlink>
</TextBlock>
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
And in UI test case i have used below code to access it:
AutomationElement mainGrid = null;
mainGrid = aeCryptoCalc.FindFirst(TreeScope.Subtree,
new PropertyCondition(AutomationElement.AutomationIdProperty,
"CompanyGrid"));
AutomationElement templateLink = null;
templateLink = mainGrid.FindFirst(TreeScope.Descendants,
new PropertyCondition(AutomationElement.AutomationIdProperty,
"TemplateLoadLink"));
InvokePattern itemPattern = (InvokePattern)templateLink.GetCurrentPattern(InvokePattern.Pattern) ;
itemPattern.Invoke();
but still Link is not getting clicked . Can someone suggest on this.
Related
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 a ListBox in my WPF MVVM app using the following code:
<GroupBox Grid.Column="0" Margin="0,0,0,-58">
<DockPanel>
<TextBlock DockPanel.Dock="Top"
HorizontalAlignment="Center"
Margin="0,0,0,8"
FontWeight="Bold"
Text="{x:Static p:Resources.AvaliableLEDsLabel}" />
<ListBox Name="AvailableLEDsListbox" SelectionMode="Extended"
dd:DragDrop.IsDragSource="True"
dd:DragDrop.IsDropTarget="True"
dd:DragDrop.DropHandler="{Binding}"
ItemTemplate="{StaticResource DataTemplateListBoxItem}"
ItemsSource="{Binding AvailableLeds}"
ScrollViewer.VerticalScrollBarVisibility="Hidden"
>
<ListBox.GroupStyle>
<StaticResource ResourceKey="StyleListBoxGroup" />
</ListBox.GroupStyle>
</ListBox>
</DockPanel>
</GroupBox>
This displays grouped lists of devices, with LEDs under them. The DataTemplate is the following:
<GroupStyle x:Key="StyleListBoxGroup">
<GroupStyle.HeaderTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Button Command="{Binding HideGroupCommand}">X</Button>
<TextBlock VerticalAlignment="Center"
HorizontalAlignment="Left"
FontWeight="Bold"
Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
<DataTemplate x:Key="DataTemplateListBoxItem">
<TextBlock x:Name="LedId" Text="{Binding LedId}"/>
</DataTemplate>
I would like to make the X button in the header hooked up to the HideGroupCommand toggle the hiding of all the items under that particular header. How would I go about doing this? Thanks in advance.
You have few options.
First one :
You would need to have a property in your view model something like 'ListBoxVisibility' then u would bind that property to your UI. In command text u just changed visibility property of that property in view model- so u have it reflected on UI. This visibility property can be of type 'bool' , or 'Visibility' or whatever. Only if it's type of Visibility u don't need converter when binding.
NOTE : Some people use it - even though it kinda goes out of general principel of MVVM patter. But sometimes u have to do it.
Second
If wanna stick to MVVM , then u need to fully separate your UI from your viewmodel. Create click event and change visibility.
I have a comboBox that is styled to have rows of text blocks and check boxes to allow user to check a list of different things. What I am attempting to do is disable selection of a row in the the combobox.
My View Code:
<ComboBox ItemsSource="{Binding HeaderList}"
IsSelected="False"
HorizontalAlignment="Left"
Height="10"
x:Name="ComboBox">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding IsChecked}"/>
<TextBlock Text="{Binding HeaderName}"/>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Here is a picture of my Drop Down:
Here is a picture of what I don't want:
I want to disable the ability for the user to select a specific row, but keep the ability for them to select various check boxes in the drop down. Is there a way to style this?
I had the same issue, i solved it by using a ToggleButton in combination with a Popup (instead of using a ComboBox)
Note: Not tested
<ToggleButton x:Name="filterButton" />
<Popup x:Name="popup"
AllowsTransparency="True"
StaysOpen="False"
PlacementTarget="{Binding ElementName=filterButton}"
IsOpen="{Binding ElementName=filterButton,Path=IsChecked,Mode=TwoWay}">
<ItemsControl ItemsSource="{Binding HeaderList}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding IsChecked}"/>
<TextBlock Text="{Binding HeaderName}"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Popup>
You can try to set the selectedindex of your combobox to -1 in the selectionchanged event
private void myComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
myComboBox.SelectedIndex = -1;
}
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";
}
<ComboBox x:Name="c1" Margin="21,134,228,-184" BorderBrush="{x:Null}" BorderThickness="6" Background="{x:Null}" Foreground="#FFFF0017" />
List<String> source = new List<String>();
c1.ItemsSource = source;
c1.SelectedIndex = 0;
I can see the items but I can't select them? and I can't scroll??? like when I add more than the size of the combo box,
it should appear a scroll? I'm coming from windows store c# and that is the way it is over there.
I want it to make it work just as a regular combobox, you click on it and it will appear a scrollable list of items that you can select... Thanks!
It is not recommended to use combobox control. Use the ListPicker Control.
Steps :
Download the nuget package from this link: https://www.nuget.org/packages/WPtoolkit/
Add a reference to the top of your xaml file :
xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"
Use ListPicker as shown below :
<toolkit:ListPicker Height="50" ScrollViewer.VerticalScrollBarVisibility="Auto" ItemsSource="{Binding ElementName=ConverterPage, Path=Locations}" Margin="179,129,70,434" Name="cmbCurrFrom">
<toolkit:ListPicker.ItemTemplate>
<DataTemplate>
<TextBlock FontSize="30" Foreground="Black" Text="{Binding Path=Location}"></TextBlock>
</DataTemplate>
</toolkit:ListPicker.ItemTemplate>
<toolkit:ListPicker.FullModeItemTemplate>
<DataTemplate>
<TextBlock FontSize="30" Foreground="Black" Text="{Binding Path=Location}"></TextBlock>
</DataTemplate>
</toolkit:ListPicker.FullModeItemTemplate>
</toolkit:ListPicker>