Why does this happen with Datagrid? - silverlight

I've a Silverlight app (Silverlight 4 in VS2010) wherein I've a datagrid. I wanted to set the border for the datagrid rows. So in the <DataTemplate> I wrote this:
<Border BorderBrush="Black" BorderThickness="1"></Border>
This worked. Now I wanted to draw border only in the bottom and right and I did this:
<Border BorderBrush="Black">
<Border.BorderThickness>
<Thickness Bottom="1" Left="0" Top="0" Right="1"/>
</Border.BorderThickness>
</Border>
But this throws a XAML parsing error - Cannot set the read-only property Bottom
Why would this happen? Is there any alternatives to do the same?

<Border BorderBrush="Black" BorderThickness="0,0,1,1" />

Related

Stretch WPF ListView Template layout [duplicate]

I want to have the ListItems to extend with their orange background the full width of the Listbox.
Currently they are only as wide as the FirstName + LastName.
I've set every element I can to: HorizontalAlignment="Stretch".
I want the background of the ListboxItems to expand as the user stretches the Listbox so I don't want to put in absolute values.
What do I have to do so that the background color of the ListBoxItems fill the width of the ListBox?
<Window x:Class="TestListBoxSelectedItemStyle.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TestListBoxSelectedItemStyle"
Title="Window1" Height="300" Width="300">
<Window.Resources>
<local:CustomerViewModel x:Key="TheDataProvider"/>
<DataTemplate x:Key="CustomerItemTemplate">
<Border CornerRadius="5" Background="Orange" HorizontalAlignment="Stretch" Padding="5" Margin="3">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch" Width="Auto">
<TextBlock HorizontalAlignment="Stretch">
<TextBlock.Text>
<MultiBinding StringFormat="{}{0} {1}">
<Binding Path="FirstName"/>
<Binding Path="LastName"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</StackPanel>
</Border>
</DataTemplate>
</Window.Resources>
<Grid>
<ListBox ItemsSource="{Binding Path=GetAllCustomers, Source={StaticResource TheDataProvider}}"
ItemTemplate="{StaticResource CustomerItemTemplate}"/>
</Grid>
</Window>
I found another solution here, since I ran into both post...
This is from the Myles answer:
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter>
</Style>
</ListBox.ItemContainerStyle>
This worked for me.
I'm sure this is a duplicate, but I can't find a question with the same answer.
Add HorizontalContentAlignment="Stretch" to your ListBox. That should do the trick. Just be careful with auto-complete because it is so easy to get HorizontalAlignment by mistake.
If your items are wider than the ListBox, the other answers here won't help: the items in the ItemTemplate remain wider than the ListBox.
The fix that worked for me was to disable the horizontal scrollbar, which, apparently, also tells the container of all those items to remain only as wide as the list box.
Hence the combined fix to get ListBox items that are as wide as the list box, whether they are smaller and need stretching, or wider and need wrapping, is as follows:
<ListBox HorizontalContentAlignment="Stretch"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
(credits for the scroll bar idea)
Since the border is used just for visual appearance, you could put it into the ListBoxItem's ControlTemplate and modify the properties there. In the ItemTemplate, you could place only the StackPanel and the TextBlock. In this way, the code also remains clean, as in the appearance of the control will be controlled via the ControlTemplate and the data to be shown will be controlled via the DataTemplate.
The fix for me was to set property HorizontalAlignment="Stretch" on ItemsPresenter inside ScrollViewer..
Hope this helps someone...
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBox">
<ScrollViewer x:Name="ScrollViewer" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Foreground="{TemplateBinding Foreground}" Padding="{TemplateBinding Padding}" HorizontalAlignment="Stretch">
<ItemsPresenter Height="252" HorizontalAlignment="Stretch"/>
</ScrollViewer>
</ControlTemplate>
</Setter.Value>
</Setter>
I also had the same problem, as a quick workaround, I used blend to determine how much padding was being added. In my case it was 12, so I used a negative margin to get rid of it. Now everything can now be centered properly

Is there a way to see DropShadowEffect on designtime?

I want to attach a DropShadowEffect on a Border control. I see it on runtime but not in the designer.
<Grid>
<Border Background="LightGray"
BorderBrush="DarkGray"
BorderThickness="1"
ClipToBounds="True"
Width="400"
Height="100">
<Border Background="Transparent"
BorderBrush="Black"
BorderThickness="0,10,0,0"
Margin="0,-11,0,0">
<Border.Effect>
<DropShadowEffect ShadowDepth="0"/>
</Border.Effect>
</Border>
</Border>
</Grid>
It's quite annoying, especially if working on custom control library.
The former and now apparently obsolete DropShadowBitmapEffect works on run- and designtime.
Edit:
This not a duplicate of other questions like Here as it is quite the opposite problem. The shadow effect appears at runtime, but not in the designer. Just try it out with NET-Framework WPF Project and the code above.

WPF IDataErrorInfo issues

I've used WPF and IDataErrorInfo in the past apps to display errors to the user via a controltemplate by putting an image in the adorner and adding a tooltip to the image like this;
<Style x:Key="textStyle" TargetType="TextBox">
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<DockPanel LastChildFill="True">
<Border BorderBrush="Orange"
BorderThickness="2"
CornerRadius="4"
SnapsToDevicePixels="True">
<Border.Effect>
<DropShadowEffect BlurRadius="10"
ShadowDepth="0"
Color="Orange" />
</Border.Effect>
<DockPanel>
<Image Width="16"
Height="16"
Margin="-20,0,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
RenderOptions.BitmapScalingMode="HighQuality"
Source="{StaticResource imgError}"
ToolTip="{Binding ElementName=adornedElement,
Path=AdornedElement.(Validation.Errors).CurrentItem.ErrorContent}"
ToolTipService.ShowDuration="30000" />
<AdornedElementPlaceholder Name="adornedElement" />
</DockPanel>
</Border>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
With the appropriate implementation of IDataErrorInfo in the ViewModel and setting Textbox in the view accordingly the image and tooltip are shown;
<TextBox Name="txt"
Grid.Column="0"
Height="40"
Background="Aqua"
Style="{StaticResource textStyle}"
Text="{Binding Path=Text,
UpdateSourceTrigger=PropertyChanged,
ValidatesOnDataErrors=True}" />
<TextBlock Grid.Column="1"
Height="40"
Background="AliceBlue"
Text="{Binding ElementName=txt,
Path=(Validation.Errors).CurrentItem.ErrorContent}" />
The above code displays correctly in my previous apps and shows the error in the image tooltip as confirmed by the Textblock.
However, in my current app which is built using Prism I can't get the Image to display. The TextBlock updates correctly and I can set the error to the TextBox tooltip via a style trigger without any issue. The problem is I can't seem to get the image (or anything else) to display in the Adorner. The Image is not shown and border is not changed.
The difference between previous apps and this is that the view is in a Region in a ContentControl and I've used dependency injection to inject the viewmodel into the view constructor and set the DataContext.
I can't figure out why this doesn't work when it did previously. I think I may need to include an AdornerDecorator somewhere but I'm perplexed as to where having tried it in a few places without success. Any ideas how I can ensure the Adorner is shown?
Used an AdornerDecorator to wrap the element containing the texbox and all works fine.

Getting a Border Control to Have Sunken Border

I want my to have a sunken border like a textbox. How to do this? Is there a way to get the controltemplate to mimc the parent border?
There is no theme for you to use, but you can work around like this:
Using this MSDN model (http://i.msdn.microsoft.com/dynimg/IC84967.gif):
Here's my recommendation: (sunken inner)
Just change the height/width of the outside border and you use this block of XAML like a TextBox. Reverse the two border tags if you want an outder border instead. Should be easy for you.
<Border Width="100" Height="200"
BorderBrush="Gainsboro" BorderThickness="0,0,5,5">
<Border BorderBrush="Gray" BorderThickness="5,5,0,0">
<TextBox Text="Hello World"
BorderThickness="0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" />
</Border>
</Border>
Special thanks to: Style a border with a different brush color for each corner
Should look like this:
You can try something like this
<Border Margin="20" BorderThickness="0.5" BorderBrush="Gray">
<Border BorderThickness="1,1,0,0" BorderBrush="DarkGray">
<ContentPresenter />
</Border>
</Border>
You might need to play with the colours though.

Get the scroll position from a RichTextBox?

I've created a highlighting mechanism for a RichTextBox in Silverlight 4. It'll get character positions and draw rectangle(s) over the text.
The trouble I have now is with scrolling on the RichTextBox. As I scroll all of my precious highlighting gets left behind. Is there any way I can add an event handler to a scroll event and/or a scrolling position of the RichTextBox? Or is there some better way in which I can link the position of the highlighting rectangles to the RichTextBox?
The trick would be to get what ever panel (I guess its a Canvas?) that you are overlaying the RichTextBox with to actually exist within the same ScrollViewer that rich text exists in.
The following is very rough idea but should get you on the path to reasonable solution.
You can do this using a custom style for the RichTextBox. The default style for this control can be found here.
Copy this style into a resource in your containing UserControl and point your RichTextBox Style property at it. So far nothing is different but now you can play about with the template. The relevant portion currently looks like this:-
<Border x:Name="MouseOverBorder" BorderThickness="1" BorderBrush="Transparent">
<ScrollViewer x:Name="ContentElement" Padding="{TemplateBinding Padding}" BorderThickness="0" IsTabStop="False" />
</Border>
Now we can tweak it like this:-
<Border x:Name="MouseOverBorder" BorderThickness="1" BorderBrush="Transparent">
<ScrollViewer Padding="{TemplateBinding Padding}" BorderThickness="0" IsTabStop="False">
<Grid>
<ContentControl x:Name="ContentElement" />
<Canvas x:Name="HighlightOverlay" />
</Grid>
</ScrollViewer>
</Border>
You'll note that we've moved the name "ContentElement" from the ScrollViewer to the new ContentControl. Having a FrameworkElement called "ContentElement" is the only feature that the RichTextBox stipulates about its template.
Now overlaying this ContentControl we can place a Canvas where you can place your highlighting rectangles. If the user scrolls this RichTextBox the whole Grid containing both the Content and the Highlights will scroll together.
The only remaining trick is acquiring the "HighlightOverlay" so that you can add your rectangle to it. Here is some code that will grab it:-
private Canvas HightlightOverlay;
public MyUserControl()
{
InitializeComponent();
MyRichText.LayoutUpdated += MyRichText_LayoutUpdated;
}
void MyRichText_LayoutUpdated(object sender, EventArgs e)
{
HightlightOverlay = MyRichText.Descendents()
.OfType<Canvas>()
.FirstOrDefault(elem => elem.Name == "HighlightOverlay");
}
You will be wondering where the Descendents method is coming from, it is here.
Anthony W Jones came up with a brilliant solution. There were just a couple tweaks to the XAML I had to make.
As suggested I started with this inside the template:
<Border x:Name="MouseOverBorder" BorderThickness="1" BorderBrush="Transparent">
<ScrollViewer Padding="{TemplateBinding Padding}" BorderThickness="0" IsTabStop="False">
<Grid>
<ContentControl x:Name="ContentElement" />
<Canvas x:Name="HighlightOverlay" />
</Grid>
</ScrollViewer>
</Border>
But the ContentControl messed things up somehow and you can't actually type into the RichTextBox anymore. Also, the scroll bars weren't showing up.
But I found the two changes necessary to make this work:
<Border x:Name="MouseOverBorder" BorderBrush="Transparent" BorderThickness="1">
<ScrollViewer BorderThickness="0" IsTabStop="False" Padding="{TemplateBinding Padding}" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Grid>
<Grid x:Name="ContentElement" />
<Canvas x:Name="HighlightOverlay" />
</Grid>
</ScrollViewer>
</Border>
Adding HorizontalScrollBarVisibility="Auto" and VerticalScrollBarVisibility="Auto" brought the scroll bars back, and simply using Grid instead of the ContentControl made the RichTextBox editable again.

Resources