<Grid>
<Canvas>
<TextBox Name="txt" IsReadOnly="True" Width="620" VerticalAlignment="Center"
Canvas.Left="340" Canvas.Top="5" Text="{Binding RowTitle2,Mode=OneWay}"
ToolTipService.ToolTip="{Binding Path=Text, RelativeSource={RelativeSource Self}}"
TextWrapping="NoWrap" HorizontalAlignment="Stretch"/>
</Canvas>
</Grid>
this way there is no tooltip, so how to add one ?
here i create dynamically records(txtboxes in the grid)
but on a similar example everything works just fine(no dynamilcall creation of txtboxes)
<Grid>
<Canvas>
<TextBox Name="txt" Margin="0,5,5,0" IsReadOnly="True" Width="620" VerticalAlignment="Center"
Canvas.Left="-200" Canvas.Top="-5"
ToolTipService.ToolTip="{Binding Path=Text, RelativeSource={RelativeSource Self}}"
TextWrapping="NoWrap" HorizontalAlignment="Stretch"/>
</Canvas>
</Grid>
What's the point here ? Its a bit confusing to use ReadOnly text box in a canvas which is located in a grid. Instead use a TextBlock which also improves performance, prevents memory leak, and looks better.
<Grid>
<TextBlock Margin="0,5,5,0"
VerticalAlignment="Center"
HorizontalAlignment="Stretch"
TextWrapping="NoWrap"
Text="{Binding RowTitle2}"
ToolTipService.ToolTip="{Binding Path=Text, RelativeSource={RelativeSource Self}}"
/>
</Grid>
Related
I have successfully created a textbox that displays / collapses an error message depending upon a validation rule set in its model / vm. The code goes like this for the email for ex.:
<StackPanel Grid.Row="3" Grid.Column="1">
<TextBox MaxLength="200" x:Name="mailTextBox"
Style="{StaticResource SectionEditPropertyTextBox}"
Text="{Binding Email, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
<ContentPresenter Visibility="{Binding ElementName=mailTextBox, Path=(Validation.HasError), Converter={StaticResource BooleanToVisibilityConverter}, ConverterParameter=True }"
Content="{Binding ElementName=mailTextBox, Path=(Validation.Errors).CurrentItem}"
HorizontalAlignment="Left">
<ContentPresenter.ContentTemplate>
<DataTemplate>
<Label Style="{StaticResource SectionEditErrorLabel}" Content="{Binding Path=ErrorContent}"/>
</DataTemplate>
</ContentPresenter.ContentTemplate>
</ContentPresenter>
</StackPanel>
Since I have a bunch of these, I would have liked to put all of this in a control template and relocate this in a common resource file.
My template looks like this:
<ControlTemplate x:Key="FormTextBox" TargetType="{x:Type TextBox}">
<StackPanel Grid.Row="{TemplateBinding Grid.Row}" Grid.Column="{TemplateBinding Grid.Column}">
<TextBox x:Name="validableText" MaxLength="{TemplateBinding MaxLength}"
Style="{StaticResource SectionEditPropertyTextBox}"
Text="{TemplateBinding Text}" />
<ContentPresenter Visibility="{Binding ElementName=validableText, Path=(Validation.HasError), Converter={StaticResource BooleanToVisibilityConverter}, ConverterParameter=True }"
Content="{Binding ElementName=validableText, Path=(Validation.Errors).CurrentItem}"
HorizontalAlignment="Left">
<ContentPresenter.ContentTemplate>
<DataTemplate>
<Label Style="{StaticResource SectionEditErrorLabel}" Content="{Binding Path=ErrorContent}"/>
</DataTemplate>
</ContentPresenter.ContentTemplate>
</ContentPresenter>
</StackPanel>
</ControlTemplate>
and I link to it like this:
<TextBox Grid.Row="3" Grid.Column="1" MaxLength="200" Template="{StaticResource FormTextBox}"
Text="{Binding Email, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
Unfortunately, it doesn't perform any validation so the binding must be broken somehow...
Please advise...
Thanks.
You won't need the Grid.Row and Grid.Column bindings in the Template StackPanel since the StackPanel won't be the direct child of a Grid anyway,
TemplateBinding is always a OneWay binding so the Text property for the Templated TextBox will never get updated. Change it to a regular Binding with RelativeSource and TwoWay
Change ElementName=validableText to RelativeSource={RelativeSource TemplatedParent} in the bindings for ContentPresenter since we want to perform the validation check on the Templated TextBox and not the TextBox inside the Template.
<ControlTemplate x:Key="FormTextBox" TargetType="{x:Type TextBox}">
<StackPanel>
<TextBox x:Name="validableText"
MaxLength="{TemplateBinding MaxLength}"
Style="{StaticResource SectionEditPropertyTextBox}"
Text="{Binding RelativeSource={RelativeSource TemplatedParent},
Path=Text,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}" />
<ContentPresenter Visibility="{Binding RelativeSource={RelativeSource TemplatedParent},
Path=(Validation.HasError),
Converter={StaticResource BooleanToVisibilityConverter}
ConverterParameter=True}"
Content="{Binding RelativeSource={RelativeSource TemplatedParent},
Path=(Validation.Errors).CurrentItem}"
HorizontalAlignment="Left">
<ContentPresenter.ContentTemplate>
<DataTemplate>
<Label Style="{StaticResource SectionEditErrorLabel}" Content="{Binding Path=ErrorContent}"/>
</DataTemplate>
</ContentPresenter.ContentTemplate>
</ContentPresenter>
</StackPanel>
</ControlTemplate>
On a side note, another alternative that you have here is to create a UserControl with the original piece of Xaml that you had. You could introduce the Dependency Properties needed for your scenario (Text etc.). It would only require small changes.
I am trying to add filtering to my WPF app, so I figured that I want to have an ellipse, and inside it will be a TextBox whose Text will be bound to a FilterText property in my ViewModel.
What I have tried:
<TextBox
Width="30"
Height="30">
<TextBox.Template>
<ControlTemplate>
<Grid>
<Ellipse Stroke="Black" StrokeThickness="1" />
<ContentPresenter
HorizontalAlignment="Center"
VerticalAlignment="Center"
Content="{Binding FilterText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
TextElement.Foreground="Black" />
</Grid>
</ControlTemplate>
</TextBox.Template>
</TextBox>
I took this from the same example, but with Label.
This displays the ellipse, but no TextBox inside it.
How can I create an ellipse WITH a TextBox?
Try this
<Grid>
<Ellipse Stroke="Black" StrokeThickness="1"/>
<TextBox Text="{Binding FilterText, UpdateSourceTrigger=PropertyChanged}"
VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Grid>
Fixed it by wrapping the TextBox inside a Border and setting the Border's CornerRadius:
<Border
Width="30"
Height="30"
BorderBrush="Black"
BorderThickness="1"
CornerRadius="30">
<TextBox
HorizontalAlignment="Center"
VerticalAlignment="Center"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
Background="Transparent" //important to lose the TextBox look
BorderBrush="Transparent" //important to lose the TextBox look
BorderThickness="0" //important to lose the TextBox look
Text="{Binding FilterText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</Border>
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?
I've got a Wpf Application and I'm having some speed/time issues. I've got a Grid with 2 columns. The left column contains a panel with a ListBox, and when one of the items is selected it creates a new panel and sets it at the right column of the Grid. So I've got a fixed panel on the left and a changing panel on the right.
My right panel contains some details and a ListBox. When I keep changing the right panel (change selection of the left panel) it gets really slow and UI freezes. I was able to find the issue, and it was with my ListBox. It has a complex ItemTemplate and this could explain why it is slow.
My ListBox ItemTemplate:
<DataTemplate>
<StackPanel Orientation="Vertical" VerticalAlignment="Center" HorizontalAlignment="{Binding ., Converter={StaticResource MyConverter}}">
<TextBox Style="{StaticResource MyStyle}" Text="{Binding Property, Converter={StaticResource MyConverter}}" HorizontalAlignment="{Binding ., Converter={StaticResource MyConverter}}" FontSize="10" Visibility="{Binding Property, Converter={StaticResource MyConverter}}"/>
<StackPanel Orientation="Vertical" VerticalAlignment="Center" HorizontalAlignment="{Binding ., Converter={StaticResource MyConverter}}">
<Border Padding="8" CornerRadius="10,10,10,10" Background="{Binding ., Converter={StaticResource MyConverter}}">
<StackPanel Orientation="Vertical">
<TextBox Style="{StaticResource MyStyle}" Text="{Binding Property}" Visibility="{Binding ., Converter={StaticResource MyConverter}}" FontSize="14" FontWeight="DemiBold" TextWrapping="Wrap" HorizontalAlignment="{Binding ., Converter={StaticResource MyConverter}}"/>
<StackPanel Orientation="Vertical" Visibility="{Binding Property, Converter={StaticResource MyConverter}}" HorizontalAlignment="Center">
<Image Source="{Binding Property, Converter={StaticResource MyConverter}}" MaxWidth="800" MaxHeight="200" Visibility="{Binding Property, Converter={StaticResource MyConverter}}"/>
<Image gif:ImageBehavior.AnimatedSource="ImageSource" Width="200" MaxHeight="200" Visibility="{Binding Property, Converter={StaticResource MyConverter}}"/>
</StackPanel>
<TextBox Style="{StaticResource MyStyle}" Text="{Binding ., Converter={StaticResource MyConverter}}" FontSize="14" TextWrapping="Wrap" VerticalAlignment="Stretch" HorizontalAlignment="{Binding ., Converter={StaticResource MyConverter}}"/>
</StackPanel>
</Border>
</StackPanel>
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="{Binding ., Converter={StaticResource MyConverter}}" Margin="0, 2, 0, 0" Visibility="{Binding Property, Converter={StaticResource MyConverter}}">
<Image Source="ImageSource" Margin="0,0,0,5" MaxHeight="10" VerticalAlignment="Center"/>
<TextBox Style="{StaticResource MyStyle}" Text="{Binding Property, Converter={StaticResource MyConverter}}" VerticalAlignment="Center" FontSize="10" TextWrapping="Wrap"/>
</StackPanel>
</StackPanel>
</DataTemplate>
Given this, what are some ways to speed things up?
I'm trying to create a listbox template (for the items). This is what I've got.
<Window.Resources>
<DataTemplate x:Key="ItemTemplate">
<Grid Margin="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="60"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0">
<TextBlock Text="TEKS" FontSize="20" FontWeight="Bold" Background="#FF502F8F" Foreground="White" Width="{Binding Path=Width, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type StackPanel}}}" TextAlignment="Center" />
<TextBlock Text="{Binding Level}" FontSize="24" Background="#FF058C44" HorizontalAlignment="Center" Width="{Binding Path=Width, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type StackPanel}}}" Foreground="White" TextAlignment="Center" FontFamily="Segoe UI Light" />
</StackPanel>
<TextBlock Grid.Column="1" Text="{Binding Owner}" FontSize="20" FontWeight="Bold" TextWrapping="Wrap" />
</Grid>
</DataTemplate>
</Window.Resources>
<Grid x:Name="LayoutRoot" DataContext="{Binding Source={StaticResource SampleDataSource}}">
<ListBox ItemTemplate="{DynamicResource ItemTemplate}" ItemsSource="{Binding Collection}" Margin="44,39,82,103" Style="{DynamicResource ListBoxStyle}"/>
</Grid>
And this is image how it looks.
Can you see the textblock extends more the width? I want to show the string wrap inside the listbox. What am I doing wrong?
Disable horizontal scrolling:
<ListBox ScrollViewer.HorizontalScrollBarVisibility="Disabled" ...>
Enable text wrapping (already the case):
<TextBlock TextWrapping="Wrap" ...>