i need to remove red rectangle around combobox. I have setup combobox in xaml like (below) this and i`m trying to override of the Validation.ErrorTemplate.
<ComboBox x:Name="comboPodkategoria"
Margin="0,3,0,0"
IsSynchronizedWithCurrentItem="False"
IsEditable="False"
ItemsSource="{Binding Source={StaticResource PodKategoriaLookup}, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}"
SelectedValue="{Binding IDPodKategoria}"
DisplayMemberPath="kat_popis" SelectedValuePath="IDPodkat" TabIndex="5" Style="{StaticResource combostyle}">
<Validation.ErrorTemplate>
<ControlTemplate>
</ControlTemplate>
</Validation.ErrorTemplate>
</ComboBox>
And style for removing red rectangle, but a have some error in xaml saying that Visibility property is not recognized or is not accessible. Style definition is below.
<Style x:Key="combostyle">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="Visibility" TargetName="NotValid" Value="Visible"/>
</Trigger>
</Style.Triggers>
Any idea? :(
Use this to modify the Validation.ErrorTemplate
<ControlTemplate x:Key="ComboBoxValidationErrorTemplate">
<DockPanel>
<Border BorderBrush="Blue" BorderThickness="4">
<AdornedElementPlaceholder />
</Border>
</DockPanel>
</ControlTemplate>
And then use it in your ComboBox like
<ComboBox Validation.ErrorTemplate="{StaticResource ComboBoxValidationErrorTemplate}"
...>
To have no indication of a Validation Error, remove the DockPanel, set Visibility to Collapsed or any other way you like.
Almost forgot, probably the easiest way to remove the "Red Border"
<ComboBox Validation.ErrorTemplate="{x:Null}"
...>
Add your Combobox, Validation.ErrorTemplate="{x:Null}" ; this code is ignore errors.
The setter in your trigger is setting the Visibility property of an element named "NotValid". That is not defined in the XAML you posted. If there is no element named "NotValid", that is your problem.
Related
I've got a ListBox that's declared like this:
<ListBox ItemsSource="{Binding Contracts}" SelectedItem="{Binding SelectedContract}">
<ListBox.ItemTemplate>
<DataTemplate>
<ListBoxItem Content="{Binding Name}">
<ListBoxItem.ToolTip>
<Grid>
[code omitted for reasons of clarity]
</Grid>
</ListBoxItem.ToolTip>
</ListBoxItem>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I expected the normal selection behavior since I play with the item's ToolTip rather than its content structure.
However, clicking an item's name doesn't focus/select that item. Only by clicking that tiny space between each item (easiest way would be the space between an item's name and the ListBox's border) the item gets focused/selected.
Of course, I googled around and thought I'd found the culprit (event doesn't bubble up). But any solution provided here on SO or elsewhere, e. g. adding code like this:
<ListBoxItem.Style>
<Style TargetType="ListBoxItem">
<Style.Triggers>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="IsSelected" Value="True" />
</Trigger>
</Style.Triggers>
</Style>
</ListBoxItem.Style>
turned out to not solve the problem. So, I assume I do something wrong and I'm just too blind to see it. And while there might be solutions using code-behind, I prefer to stick with clean and pure XAML.
Please help me, understanding my mistake and solving it.
if the purpose is add ToolTip for ListBoxItem, you can use ItemContainerStyle. ListBox creates ListBoxItems for each databound item, adding ListBoxItem into
DataTemplate isn't necessary, if it breaks some functionality, try to avoid it
<ListBox>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem" BasedOn="{StaticResource {x:Type ListBoxItem}}">
<Setter Property="ToolTip">
<Setter.Value>
<Grid>
<TextBlock Text="{Binding .}"/>
</Grid>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding .}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
edit: I used Snoop app to check your variant with ListBoxItem in DataTemplate. There is 2 ListBoxItems in visual tree of each ListBox element, maybe one of prevent selection of another
I have a ListBox in which each item is a StackPanel. The StackPanel consist of an Image and a TextBlock below it:
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="10">
<Image>
<Image.Source>
<BitmapImage UriSource="{Binding Path=ImageFilePath}"/>
</Image.Source>
</Image>
<TextBlock Text="Title" TextAlignment="Center"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
It looks like this:
When the user select an item, I get the default blue rectangle that surround the StackPanel:
Now, I want to make a different border for the selected-item, but I want it to surround only the image.
I know how to make a control template and put a custom border around the ContentPresenter, but this, of course, will surround the whole StackPanel, not only the Image.
I don’t know if making changes to the ContentPresenter is possible, and if it is a good idea at all. If there is other way to achieve the look I want, it will be fine as well.
Right, the ListBox's own ContentPresenter isn't helpful for what you're doing. You want to a) eliminate the ListBox's own selection visuals and b) replace them with something more suitable in the DataTemplate for your items.
The default selection visual is applied by the default template for ListBoxItem. So replace that template. Using a Style in the resources for your ListBox, apply your own control template to ListBoxItem. Not much to it, just present the content and don't provide a selection background. Then you handle the selection visuals with a trigger in your data template, where your image and your label are defined and you can apply changes to one and not the other. The below example works for me.
Note that there's some fiddling with the HorizontalAlignment on the Border element to make it cling to the Image element within it. Also, I wrote a quickie test viewmodel whose Items property is called Items; I assume this is not the name of the collection member you're using to populate your own ListBox.
<ListBox
Margin="8"
ItemsSource="{Binding Items}"
>
<ListBox.Resources>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Grid>
<ContentPresenter />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.Resources>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Border
x:Name="HighlightBorder"
BorderThickness="4"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Margin="10"
>
<Border.Style>
<Style TargetType="Border">
<!-- MUST set default BorderBrush via a style, if you set it at all.
As an attribute on the Border tag, it would override the effects of
the trigger below.
-->
<Setter Property="BorderBrush" Value="Transparent" />
</Style>
</Border.Style>
<Image Source="{Binding ImageFilePath}" />
</Border>
</Grid>
<DataTemplate.Triggers>
<DataTrigger
Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=ListBoxItem}}"
Value="True">
<Setter TargetName="HighlightBorder" Property="BorderBrush" Value="Orange" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I have a MainWindow.XAML
TextBox is added to it
TextBox text binding is done
When I add StringFormat inside binding (in MainWindow.XAML) it works
When I add StringFormat inside Style, it's not working
below is the code from style and MainWindow.xaml
<TextBox Grid.Row="1" Grid.Column="4" Style="{StaticResource TextBoxStyle}" Text="{Binding CustomerAmount,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" HorizontalAlignment="Stretch" Margin="10,0,0,0"/>
<Style x:Key="TextBoxStyle" TargetType="{x:Type TextBox}" >
<Setter Property="Text" Value="{Binding Text, RelativeSource={RelativeSource Self},StringFormat='#,###,###,##0.00;(#,###,###,##0.00)'}"></Setter>
</Style>
Well you've basically applied two Text binding's now, one in MainWindow and one in Style.
The Text property set in MainWindow.xaml on the control has precedence over the one you're setting in Style, so the StringFormat you set via Style is actually never applied cos that entire Style.Setter is ignored.
A very rough way to make this work and prove the above statement is try switching your xaml to the following,
<TextBox Grid.Row="1" Grid.Column="4" Style="{StaticResource TextBoxStyle}" Tag="{Binding CustomerAmount,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" HorizontalAlignment="Stretch" Margin="10,0,0,0"/>
and Style:
<Style x:Key="TextBoxStyle"
TargetType="{x:Type TextBox}">
<Setter Property="Text"
Value="{Binding Tag,
RelativeSource={RelativeSource Self},
StringFormat='#,###,###,##0.00;(#,###,###,##0.00)',
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}" />
</Style>
This will work cos you now have Tag binding in MainWindow and Text in Style. You can switch to a custom Attached property or DP to get the same behavior
I have a ListView inside a DockPanel. I need the ListView to be stretched horizontally and centered vertically inside the DockPanel. When the ListView is disabled (IsEnabled=false) I need to change the DockPanel's background to match the disabled ListView's background color.
So, basically I want to avoid the situation that can be seen on the picture below.
<Window>
<DockPanel IsEnabled="False">
<ListView IsEnabled="False" VerticalAlignment="Center" HorizontalContentAlignment="Center">
<ListViewItem Content="AAA"/>
<ListViewItem Content="BBB"/>
<ListViewItem Content="CCC"/>
</ListView>
</DockPanel>
</Window>
However, I don't want to explicitly declare colors anywhere in my code, because I don't know what kind of background color will a ListView use in different Windows environments (I'm not sure, but I guess different Windows theme/color settings can alter the default background color of the ListView - which potentially could be different from the color that I don't want to explicitly declare).
Binding the ListView's background color to the DockPanel's background color doesn't work.
So, right now I'm using the following workaround.
<DockPanel.Style>
<Style TargetType="{x:Type DockPanel}">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=parametersListView, Path=IsEnabled}" Value="False">
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DockPanel.Style>
I've extracted the resource key that my ListView's using in its ControlTemplate. On the template there is a Trigger declared on the IsEnabled property and it sets the control's background color to the color represented by the SystemColors.ControlBrushKey key.
This seems to work, but I'm not sure if this is the right way to do this.
Is there a way to do this in a more robust fashion, or this is the best that I could do?
(On a side note: using SystemColors.ControlBrush instead of SystemColors.ControlBrushKey produces a different shade of grey, I'm not sure why.)
Why not use LstFilledChild =true
Edit:
If you name your element and use the ElementName in the binding it should work.
<DockPanel HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="{Binding Background, ElementName=myList}">
<ListView Name="myList" IsEnabled="False" HorizontalAlignment="Center" HorizontalContentAlignment="Center" >
<ListViewItem>AAA</ListViewItem>
</ListView>
</DockPanel>
Since I've asked my question the application I was working on is live and it's using the solution I've originally come up which is the following. It works well for the moment.
<Window>
<DockPanel IsEnabled="False">
<DockPanel.Style>
<Style TargetType="{x:Type DockPanel}">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=myListView, Path=IsEnabled}"
Value="False">
<Setter Property="Background"
Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DockPanel.Style>
<ListView IsEnabled="False"
VerticalAlignment="Center"
HorizontalContentAlignment="Center"
x:Name="myListView"
x:FieldModifier="private">
<ListViewItem Content="AAA"/>
<ListViewItem Content="BBB"/>
<ListViewItem Content="CCC"/>
</ListView>
</DockPanel>
</Window>
I'm using a the WPF datagrid from the Microsoft CodePlex project. I have a custom control that I want to databind to a field from the row of the datagrid. I can't for the life of me figure out how to specify a tooltip on a datagrid row.
The closest I've come is to use a RowStyle with a Setter to set the tooltip, but this only seems to work for text. When I try to put a ControlTempalte in as the Value for the ToolTip, it displays the result of calling ToString on the ControlTemplate type.
I think I need to set the "Template" property of the ToolTip, but I can't seem to figure out how to do that...
<dg:DataGrid Name="dgResults" AutoGenerateColumns="True">
<dg:DataGrid.RowStyle >
<Style TargetType="{x:Type dg:DataGridRow}">
<Setter Property="ToolTip" >
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToolTip}">
<StackPanel>
<TextBlock>txt1</TextBlock><TextBlock>txt2</TextBlock>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</dg:DataGrid.RowStyle>
</dg:DataGrid>
Figured it out... took me about 6 hours...
For some reason, I can't set the value directly using Value.Setter. If I define the content for the tooltip as a static resource though, and then set it in the Style property of the DataGrid.RowStyle it works.
So, the datagrid row style looks like:
<Style TargetType="{x:Type dg:DataGridRow}">
<Setter Property="ToolTip" Value="{StaticResource resKWIC}">
</Setter>
</Style>
</dg:DataGrid.RowStyle>
And the resource is
<Window.Resources>
<StackPanel x:Key="resKWIC">
<TextBlock>f1</TextBlock>
<TextBlock>f2></TextBlock>
</StackPanel>
</Window.Resources>
Thanks!
The key is to use the Property ToolTipService.ToolTip, instead of ToolTip - like this:
<Setter Property="ToolTipService.ToolTip" Value="My Tooltip"/>
I also got this working with a couple of changes; included incase it helps someone.
My Datadrid is bound to a list of custom objects, I wanted to display the string "Name" as a column and the string "text" in the tooltip. The trick for me (newbe) was that I had to include the Text Column and hide it for it to show up in the tooltip, i.e.:
<DataGrid AutoGenerateColumns="False" CanUserAddRows="False" EnableRowVirtualization="False" HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" IsReadOnly="True" IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding}" Name="dgrTextGroupText" VerticalContentAlignment="Stretch" Grid.Column="3" Grid.Row="1" Grid.RowSpan="6" CanUserReorderColumns="False" CanUserSortColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Name}" Width="*" />
<DataGridTextColumn Binding="{Binding Text}" Width="0" Visibility="Hidden" />
</DataGrid.Columns>
<DataGrid.RowStyle>
<Style TargetType="{x:Type DataGridRow}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=DataContext.text}" />
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
</DataGrid>
Not sure you can do it through XAML.
A easier way might be to just handle the LoadingRow event. In xaml have something like:
<dg:DataGrid Name="dgResults" AutoGenerateColumns="True"
LoadingRow="dgResults_LoadingRow"
ItemsSource="{Binding ListOfStrings}" />
Then in code behind
void dgResults_LoadingRow(object sender, DataGridRowEventArgs e)
{
DataGridRow row = e.Row;
row.ToolTip = row.DataContext as string;
}
Obviously you will have to change the code depending on how you are populating the data in the datagrid. This is also untested =)
I needed to set the tooltip dynamically based on the cell content. I'm using the tooltip to display text overflow text from the cell. The binding below is from a c# class property named CellText. Thanks to the posts above for allowing me to avoid figuring out the entire thing myself.
<DataGridTextColumn Header="HeaderText" Binding="{Binding DisplayText, Mode=OneWay}" Width="33*">
<DataGridTextColumn.CellStyle>
<Style>
<Setter Property="ToolTipService.ToolTip" Value="{Binding DisplayText, Mode=OneWay}"/>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
There's no need for the ControlTemplate. If you want the StackPanel in the ToolTip, just set it as:
<Setter Property="ToolTip">
<Setter.Value>
<StackPanel>
<TextBlock>txt1</TextBlock><TextBlock>txt2</TextBlock>
</StackPanel>
</Setter.Value>
</Setter>