How to give Data trigger property for custom usercontrol? - c#

I have created the custom usercontrol for datagrid as CustomDatagrid. And i am using that custom datagrid in another usercontrol as DatagridUserControl. I added Textblock inside the CustomDatagrid in DatagridUserControl. I gave x:Name for Textblock in DatagridUserControl.
<GridControl:CustomDatagrid Grid.Row="2" Height="260" Width="640" x:Name="GridTask" BorderThickness="0" FontSize="24" Foreground="White" SelectionChanged="slmGridTask_SelectionChanged"
ColumnWidth="*" CanUserResizeColumns="False" Background="Transparent">
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Grid Margin="-50,0,0,0" HorizontalAlignment="Left">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<WrapPanel Grid.Row="0" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="-50,0,0,0">
<TextBlock Text="{Binding Name}" TextWrapping="WrapWithOverflow"
TextAlignment="Justify" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="-20,0,0,0" />
</WrapPanel>
<Grid Margin="-60,0,0,0" Grid.Row="1" >
<TextBlock x:Name="TxtBlkDescription" Margin="0,0,0,0" TextWrapping="Wrap" Text="{Binding Description}" Visibility="Collapsed" FontWeight="Regular" Foreground="White" FontSize="18" FontFamily="Open Sans" HorizontalAlignment="Left" />
</Grid>
</Grid>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</GridControl:CustomDatagrid>
That textblock should display only if datagridrow is selected. So I added DataTrigger property for Textblock.
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Path=IsSelected, RelativeSource={RelativeSource AncestorType=DataGridRow}}" Value="True">
<Setter TargetName="TxtBlkDescription" Property="Visibility" Value="Visible" />
</DataTrigger>
</DataTemplate.Triggers>
But I received the following error
Cannot set Name attribute value 'TxtBlkDescription' on element 'TextBlock'. 'TextBlock' is under the scope of element 'SLMDatagrid', which already had a name registered when it was defined in another scope.
How to overcome this error?
Or is there is any other way to display the Textblock only if Datagridrow is selected?

Related

Link a ListBox Borderbrush property to a IsEnabled button

I have two TextBoxes, two ListBoxes, a Cancel button and an OK button.
Simplifying the problem, I would like to link the color of the Borderbrush of the second ListBox to the IsEnabled property of the OK button.
An alternative would be link that color change to the ListBoxItem background instead of the Listbox border itself.
Is it possible (maybe through Triggers or something)? If so, could you show me the way?
The XAML of the window is as follows:
<Window x:Class="Opt.ExpertSystem.View.WindowPasteRules"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:scroll="clr-namespace:Opt.ExpertSystem.View"
Title="Paste Rules Options" Width="400" Height="300">
<Window.InputBindings>
<KeyBinding Key="Esc" Command="{Binding CancelCommand}" />
</Window.InputBindings>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="28"/>
<RowDefinition Height="100*"/>
<RowDefinition Height="35"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="76*" />
</Grid.ColumnDefinitions>
<Label Content="Select Rules to Paste: " Grid.Column="0" Grid.Row="0" HorizontalAlignment="Right" HorizontalContentAlignment="Right" Margin="0,0,2,0" Width="Auto"/>
<Grid Grid.Row="1" Grid.ColumnSpan="2" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" >
<Grid.Resources>
<Style TargetType="ScrollViewer">
<Setter Property="scroll:ScrollSynchronizer.ScrollGroup" Value="Group1" />
</Style>
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition Height="50*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="5" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Content="Replace" HorizontalAlignment="Stretch" FontWeight="Bold"/>
<TextBox Margin="55,2,2,2" Text="{Binding CopyNameOrigin}" ToolTip="Non-editable field. Represents the text you want to replace." Focusable="False"/>
<Label Content="With" Grid.Column="2" HorizontalAlignment="Stretch" FontWeight="Bold"/>
<TextBox Grid.Column="2" Margin="42,2,2,2" Text="{Binding CopyNameNew, UpdateSourceTrigger=PropertyChanged}" ToolTip="Represents the results of the changes to be made." />
<ListBox ItemsSource="{Binding Path=CopiedRules}" Grid.Row="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.Column="0" BorderThickness="1" BorderBrush="CornflowerBlue" Grid.IsSharedSizeScope="True" Margin="2,0,2,10" >
<ListBox.ItemTemplate>
<DataTemplate>
<Label Content="{Binding Name}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<ListBox ItemsSource="{Binding Path=PasteRules}" Grid.Row="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.Column="2" BorderThickness="1" BorderBrush="CornflowerBlue" Margin="2,0,2,10" >
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Name}" IsChecked="{Binding IsChecked}" Margin="2,5,2,5" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
<Grid Grid.Row="2" Background="#FFECE9D8" Grid.ColumnSpan="2">
<Button Content="OK" x:Name="btnOK" IsEnabled="{Binding IsValid, UpdateSourceTrigger=PropertyChanged}" Margin="0,6,6,0" Grid.Row="3" Grid.Column="1" HorizontalAlignment="Right" VerticalAlignment="Top" Width="75" Height="23" Click="btnOK_Click" />
<Button Content="Cancel" x:Name="btnCancel" IsCancel="True" Margin="0,6,90,0" Grid.Row="3" Grid.Column="1" HorizontalAlignment="Right" VerticalAlignment="Top" Width="75" Height="23" />
</Grid>
</Grid>
</Window>
Here's a small example that changes the border brush of a listview based on the IsEnabled property of a button
<StackPanel>
<ListBox Height="100">
<ListBox.Style>
<Style TargetType="ListBox">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=okButton, Path=IsEnabled}" Value="false">
<Setter Property="BorderBrush" Value="Red"/>
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=okButton, Path=IsEnabled}" Value="true">
<Setter Property="BorderBrush" Value="Blue"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ListBox.Style>
</ListBox>
<Button IsEnabled="True" Name="okButton">true</Button>
</StackPanel>
But I would set the availability of the button on the command and not in the XAML, also I would bind the color of the ListView to the IsValid property in the ViewModel instead.

HorizontalAlignment not working on ComboBox in DataGridTextColumn

I have a DataGridTextColumn whose header consists of a TextBlock and a ComboBox. I would like the TextBlock to be left aligned and the ComboBox to be right-aligned. When I try setting that on ComboBox using HorizontalAlignment = "Right", it does not work! For the header I tried with StackPanel as well as a Grid for containing the TextBlock and ComboBox. What I am doing wrong?
<DataGrid
CanUserSortColumns="True"
IsReadOnly="True">
<DataGrid.Columns>
<DataGridTextColumn Header="Time"/>
<DataGridTextColumn>
<DataGridTextColumn.Header>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Money" VerticalAlignment="Center"/>
<ComboBox HorizontalAlignment="Right" VerticalAlignment="Center"
Width="100" ItemsSource="{Binding comboBoxItems}" SelectedIndex="0">
</ComboBox>
</StackPanel>
</DataGridTextColumn.Header>
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
Attempt with Grid:
<DataGridTextColumn.Header>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Money" VerticalAlignment="Center"/>
<ComboBox Grid.Column="1" HorizontalAlignment="Right" VerticalAlignment="Center"
ItemsSource="{Binding comboBoxItems}" SelectedIndex="0">
</ComboBox>
</Grid>
</DataGridTextColumn.Header>
EDIT 1: I would like the ComboBox to be stretched if the column is dragged to increase the column width. Otherwise atleast the ComboBox should align to the right if the column is dragged on the right side.
EDIT 2: The important thing here is that when I drag the column to increase its width, the ComboBox should fall on the right side.
use this
<DataGridTextColumn Width="120">
<DataGridTextColumn.HeaderTemplate>
<DataTemplate>
<Grid Width="{Binding Path=ActualWidth, RelativeSource={RelativeSource AncestorType={x:Type DataGridColumnHeader}}}">
<TextBlock Text="LLLLL" HorizontalAlignment="Left" Margin="5"/>
<TextBlock Text="RRRRR" HorizontalAlignment="Right" Margin="5"/>
</Grid>
</DataTemplate>
</DataGridTextColumn.HeaderTemplate>
</DataGridTextColumn>
Try DockPanel instead of StackPanel.
<DockPanel LastChildFill="True">
<TextBlock Text="Money" VerticalAlignment="Center" DockPanel.Dock="Left"/>
<ComboBox VerticalAlignment="Center" SelectedIndex="0"/>
</DockPanel>

grids Visibility binded to a TabControl SelectedItem

I have two grids contained in borders like this :
<Border BorderBrush="Gray" BorderThickness="2" Margin="5" Visibility="{Binding SelectedItem, ElementName=tcAction, Converter={StaticResource LoadChangeHeaderToVisibilityConverter}}">
<Grid x:Name="actionGrid" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" >
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text=" Card Name" HorizontalAlignment="Center" Margin="0,4,0,0" FontSize="16"/>
<Label Grid.Row="1" Content="{Binding CardName}" FontSize="14" HorizontalAlignment="Center" />
<TextBlock Grid.Row="2" Text="{Binding ActionType, StringFormat='Action Type: {0}'}" Margin="4" FontSize="13" FontWeight="ExtraBlack" HorizontalAlignment="Center"/>
<TextBlock Grid.Row="3" Text="{Binding Action, StringFormat='Action: {0}'}" Margin="4" FontSize="13" FontWeight="ExtraBlack" HorizontalAlignment="Center"/>
</Grid>
</Border>
<Border BorderBrush="Gray" BorderThickness="2" Margin="5" Visibility="{Binding SelectedItem, ElementName=tcAction, Converter={StaticResource LoadChangeHeaderToVisibilityConverter}}">
<Grid x:Name="actionCANGrid" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text=" CAN Name" HorizontalAlignment="Center" Margin="0,4,0,0" FontSize="16"/>
<Label Grid.Row="1" Content="{Binding CardName}" FontSize="14" HorizontalAlignment="Center" />
<TextBlock Grid.Row="2" Text="{Binding ActionType, StringFormat='Action Type: {0}'}" Margin="4" FontSize="13" FontWeight="ExtraBlack" HorizontalAlignment="Center"/>
<TextBlock Grid.Row="3" Text="{Binding Action, StringFormat='Action: {0}'}" Margin="4" FontSize="13" FontWeight="ExtraBlack" HorizontalAlignment="Center"/>
</Grid>
</Border>
Both of them are binded to the SelectedItem property of a TabControl. The fact here is that i want only one grid visible at a time, depending on the TabItem selected. So when Visibility is Visible for one of them, it should be Hidden for others. I am not sure how can i track the states of all the future grids, and keep only 1 in the front.
Personally I wouldn't mess with Visibility at all. That's the old WinForms way :)
Instead, I'd use a ContentControl and switch the ContentTemplate property in a DataTrigger based on the SelectedItem. I find this easier to maintain, and there's only one set of items in the visual tree at a time.
<Style TargetType="{x:Type ContentControl}">
<Setter Property="ContentTemplate" Value="{StaticResource DefaultTemplate}" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=MyTabControl, Path=SelectedIndex}" Value="0">
<Setter Property="ContentTemplate" Value="{StaticResource ActionTemplate}" />
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=MyTabControl, Path=SelectedIndex}" Value="1">
<Setter Property="ContentTemplate" Value="{StaticResource ActionCANTemplate}" />
</DataTrigger>
</Style.Triggers>
</Style>
Instead of binding the SelectedItem of the tabcontrol, Bind SelectedIndex and pass the convertParamereter to the Converter
Your Converter will be like below
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if ((int)value == (int)parameter)
{
return Visibility.Visible;
}
return Visibility.Collapsed;
}
And in your Xmal change the visibility as below
Visibility="{Binding SelectedIndex, ElementName=tcAction, Converter={StaticResource LoadChangeHeaderToVisibilityConverter}, ConverterParameter=0}">

XAML - Bind combobox in DataTemplate to a collection?

Firstly, thank you for taking the time out to read this post. All contributions are very much appreciated.
I'm having difficulty understanding how I can bind a ComboBox ItemsSource within a DataTemplate to an ObservableCollection.
Here's my code thus far:
DataTemplate Template (notice the combo's at the bottom of the template):
<DataTemplate x:Key="ListBoxCustomTemplate">
<Grid Margin="4" HorizontalAlignment="Stretch" x:Name="lstBoxItemRoomGrid" >
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" FontWeight="Bold" Text="{Binding TemplateGroupName}" />
<Image x:Name="imgDeleteListBoxItem" Grid.Row="0" Grid.RowSpan="2" Grid.Column="1" Source="/Icons/Print-Groups-Config/delete-32.png" Height="25" Cursor="Hand"
ToolTip="Remove template" VerticalAlignment="Center"
HorizontalAlignment="Right" MouseLeftButtonUp="imgDeleteListBoxItem_MouseLeftButtonUp">
<Image.Style>
<Style>
<Setter Property="Image.Visibility" Value="Hidden" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsMouseOver, ElementName=lstBoxItemRoomGrid}" Value="True">
<Setter Property="Image.Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
<TextBlock Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Text="{Binding TemplateDescription}" TextWrapping="WrapWithOverflow" />
<!-- Header Template Selection -->
<Label Grid.Row="2" Grid.Column="0" Margin="0,3,0,0" HorizontalAlignment="Left" VerticalAlignment="Bottom" Content="Select Header:" FontWeight="DemiBold" Foreground="DarkGray" />
<telerik:RadComboBox x:Name="radComboHeaderTemplate" Grid.Row="3" Grid.Column="0" Width="120" Margin="0,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Center"
ClearSelectionButtonVisibility="Visible" SelectedValue="{Binding TemplateHeaderID}" />
<!-- Footer Template Selection -->
<Label Grid.Row="2" Grid.Column="1" Margin="0,3,0,0" HorizontalAlignment="Left" VerticalAlignment="Bottom" Content="Select Footer:" FontWeight="DemiBold" Foreground="DarkGray" />
<telerik:RadComboBox x:Name="radComboFooterTemplate" Grid.Row="3" Grid.Column="1" Width="120" Margin="0,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Center"
ClearSelectionButtonVisibility="Visible" SelectedValue="{Binding TemplateFooterID}" />
</Grid>
</DataTemplate>
When my Window loads, I download the collection data from my database and store into a local collection. Note that there are two Collections, one for each of the 2 ComboBoxes in my DataTemplate.
//Header Templates
private ObservableCollection<TemplateHeaderFooter> templatesHeader = new ObservableCollection<TemplateHeaderFooter>();
//Footer Templates
private ObservableCollection<TemplateHeaderFooter> templatesFooters = new ObservableCollection<TemplateHeaderFooter>();
//--- Constructors ---
public PrintTemplateGroupsConfigWindow()
{
InitializeComponent();
//Download Data From DB
this.templatesHeader = TemplateHeaderFootersDB.GetAllTemplatesOfType(1);
this.templatesFooters = TemplateHeaderFootersDB.GetAllTemplatesOfType(2);
}
How do I get the collection Data templatesFooters & templatesHeader into the the ItemsSources of their respective ComboBoxes?
The datatemplate is for a ListBox.
<telerik:RadListBox x:Name="lstBoxPrintGroupTemplates" Height="300" Width="280" ItemsSource="{Binding}" IsEnabled="False"
ItemTemplate="{StaticResource ListBoxCustomTemplate}" Style="{StaticResource DraggableListBox}" >
Many thanks. Any help is appreciated.
Define properties wrappers over the variables of your collections and then you can bind them to comboboxes as:
ItemsSource="{Binding TemplatesHeader, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
public ObservableCollection<TemplateHeaderFooter> TemplatesHeader
{
get{return templatesHeader;}
}
Similarly you can do for other property

WPF combobox itemtemplate overrides togglebutton style

i have problem with styling the combobox's togglebutton.
my combobox xaml code looks like this:
<ComboBox Width="Auto"
HorizontalContentAlignment="Stretch"
FontFamily="HelveticaNeue-Bold"
FontSize="20"
FontWeight="Bold"
Foreground="#FFC0C0C0"
Padding="0,0,0,0"
Style="{DynamicResource navigationComboBox}"
ItemsSource="{Binding Tournaments}"
SelectedValue="{Binding SelectedTournament}">
<ComboBox.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent" />
</ComboBox.Resources>
<ComboBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True"
Orientation="Vertical"
Width="auto"
Height="{Binding Tournaments, Converter={StaticResource CollectionToHeightConverter}}"/>
</ItemsPanelTemplate>
</ComboBox.ItemsPanel>
<ComboBox.ItemTemplate>
<DataTemplate>
<DockPanel x:Name="comboDock">
<DockPanel.Background>
<ImageBrush ImageSource="{Binding Converter={StaticResource ImagePathConverter}, ConverterParameter=comboboxitem-line.png}" />
</DockPanel.Background>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="41" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<DockPanel x:Name="comboArrow"
Grid.Column="0"
Visibility="Collapsed">
<DockPanel.Background>
<ImageBrush ImageSource="{Binding Converter={StaticResource ImagePathConverter}, ConverterParameter=SportsSubMenuActive.png}" />
</DockPanel.Background>
</DockPanel>
<TextBlock x:Name="comboText"
Grid.Column="1"
FontFamily="HelveticaNeue-Bold"
FontSize="20"
FontWeight="Bold"
Foreground="#FFC0C0C0"
Padding="0,0,10,0"
Text="{Binding Path=Name}"
TextAlignment="Left"
TextWrapping="Wrap" />
</Grid>
</DockPanel>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=ComboBoxItem}}" Value="True">
<Setter TargetName="comboArrow" Property="Visibility" Value="Visible" />
<Setter TargetName="comboText" Property="Foreground" Value="#F94B01" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ComboBox.ItemTemplate>
so i'm trying to remove the background set to on togglebutton, but it is not possible. if i remove the background on itemtemplate, then i can style the toggle button background. is there any special order in the process to prevent me from changing the background of the togglebutton content if it is set in itemtemplate?
thanks in advance guys,
Kristo
Setting a property directly takes priority over any Setter(s). Instead of setting the property directly, use a Style for your DockPanel and use a Setter to set the background similar to what you do in your DataTrigger. That should allow you to change the background property elsewhere.

Categories

Resources