How to add a border line without shadow effect in wpf - wpf

the above tree view is looking with shadow effect on top left and left. I need a single thick line .
my xaml is
Margin="0,0,0,2" BorderBrush="Black" BorderThickness="1"
I need a single line but not a shodow. Can you please help me how to do it ?

One way to do it is to create simple Template for your TreeView like so:
<TreeView BorderBrush="Black" BorderThickness="1" Background="Beige">
<TreeView.Template>
<ControlTemplate TargetType="{x:Type TreeView}">
<Border
BorderBrush="{TemplateBinding BorderBrush}"
Background="{TemplateBinding Background}"
BorderThickness="{TemplateBinding BorderThickness}">
<ScrollViewer>
<ItemsPresenter/>
</ScrollViewer>
</Border>
</ControlTemplate>
</TreeView.Template>
</TreeView>

You can try this to get rid of treeview border and apply your own border:
<Border BorderThickness="1" BorderBrush="Black">
<TreeView BorderBrush="Transparent" BorderThickness="0"
</TreeView>
</Border>

Related

GridViewHeaderRowPresenter scrolls with custom TreeListView control

I have a custom TreeListView - based on the standard TreeView - with the following style:
<Style TargetType="{x:Type c:TreeListView}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type: c:TreeListView}">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
<DockPanel>
<GridViewHeaderRowPresenter DockPanel.Dock="Top" Columns="{Binding Path=Columns, RelativeSource={RelativeSource TemplatedParent}}" />
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</DockPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
As I have no ScrollViewer, the content will not scroll so if the content requires more space than is available, it looks like this:
So I added a ScrollViewer so that the style now Looks like this:
<Style TargetType="{x:Type c:TreeListView}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type: c:TreeListView}">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
<ScrollViewer Focusable="False" Padding="{TemplateBinding Padding">
<DockPanel>
<GridViewHeaderRowPresenter DockPanel.Dock="Top" Columns="{Binding Path=Columns, RelativeSource={RelativeSource TemplatedParent}}" />
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</DockPanel>
</ScrollViewer>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
With the content expanded as in the first Image, the Content is not able to scroll, but the column Header scrools as well, which is not wished for :D
Could anyone please help me so that only the content gets scrolled, and not the columns bound to the GridViewHeaderRowPresenter?
Thank you!
[EDIT]
Thanks to the related links to the right, I found the answer here.
Instead of having the DockPanel within the ScrollViewer I needed only to have the ItemsPresenter inside the ScrollViewer. So with the following Style it now works.
<Style TargetType="{x:Type c:TreeListView}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type c:TreeListView}">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
<DockPanel>
<GridViewHeaderRowPresenter DockPanel.Dock="Top" Columns="{Binding Path=Columns, RelativeSource={RelativeSource TemplatedParent}}" />
<ScrollViewer Focusable="False" Padding="{TemplateBinding Padding}">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</ScrollViewer>
</DockPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Many thanks to Nikhil Agrawal for his code!
The solution given is incomplete and will only work if you have a fixed width control. By only wrapping the ItemsPresenter the header columns will not scroll horizontally if needed. This results in shifted value columns which then mismatch the headers.
I've tried applying SelectiveScrollingGrid.SelectiveScrollingOrientation="Horizontal" to GridViewHeaderRowPresenter but haven't been successfull with that approach.
Instead, you could add a scroll viewer to the GridViewHeaderRowPresenter and to the ItemsPresenter and then synchronize them. It's not the best solution, but at least it works.
<Style TargetType="{x:Type local:TreeListView}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:TreeListView}">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
<DockPanel>
<ScrollViewer DockPanel.Dock="Top"
HorizontalScrollBarVisibility="Hidden"
Name="scrollViewerHeader"
VerticalScrollBarVisibility="Disabled">
<GridViewHeaderRowPresenter Columns="{StaticResource gvcc}"/>
</ScrollViewer>
<ScrollViewer HorizontalScrollBarVisibility="Auto"
Name="scrollViewerBody"
VerticalScrollBarVisibility="Auto">
<ItemsPresenter />
</ScrollViewer>
</DockPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
And the code behind:
public class TreeListView : TreeView
{
private ScrollViewer _scrollViewerHeader;
private ScrollViewer _scrollViewerBody;
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
_scrollViewerHeader = (ScrollViewer)Template.FindName("scrollViewerHeader", this);
_scrollViewerBody = (ScrollViewer)Template.FindName("scrollViewerBody", this);
_scrollViewerBody.ScrollChanged += (sender, e) =>
{
_scrollViewerHeader.Width = e.ViewportWidth;
_scrollViewerHeader.ScrollToHorizontalOffset(e.HorizontalOffset);
};
}
}
The way DataGrid solves it is it customizes the Template of the ScrollViewer to place the GridViewHeaderRowPresenter outside the ScrollViewer ScrollContentPresenter:
https://github.com/dotnet/wpf/blob/059ba38771aef10d2172a3ca0e247dfbfa8cefde/src/Microsoft.DotNet.Wpf/src/Themes/PresentationFramework.Aero2/Themes/Aero2.NormalColor.xaml#L987-L993
This way when the scrollbars scroll, they don't impact the header row.
The ListView that uses GridView does a similar thing here:
https://github.com/dotnet/wpf/blob/059ba38771aef10d2172a3ca0e247dfbfa8cefde/src/Microsoft.DotNet.Wpf/src/Themes/PresentationFramework.Aero2/Themes/Aero2.NormalColor.xaml#L2628
At the same time they wrap the header row in another ScrollViewer, and honestly I don't understand why.
Once I find out more I will expand on this answer. I think this approach if it works is cleaner than synchronizing scroll viewers.

Resize container without resizing text controls

I have a Custom Control containing a Canvas placed inside a Viewbox. This allows me to resize the control and everything inside the Canvas scales beautifully.
Much to my annoyance a requirement to stop any scaling of text within the control has reared its head. All other controls (mainly graphics) should scale, but not text. Text should move to the correct place upon resize, but the font should remain the same.
Any ideas how to do this?
After much head scratching I found a relatively simple workaround.
As I'm not going to need to click on any text in the control I've put all graphics inside one canvas with zOrder 1 and all text in another with zorder 0. Then I put them inside a grid so they overlap:
<ControlTemplate TargetType="{x:Type local:ContourPlot}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<Viewbox>
<Border BorderBrush="Black" BorderThickness="1">
<Canvas x:Name="cvGraph" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" >
<Rectangle Canvas.Left="40" Canvas.Top="31" Width="48" Height="41" Fill="AliceBlue"/>
</Canvas>
</Border>
</Viewbox>
<Canvas Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" >
<Label x:Name="lblTest" Canvas.Left="0" Canvas.Top="10" Content="Label" FontSize="12" />
</Canvas>
</Grid>
</Border>
</ControlTemplate>

Round a arbitrary content control

I have an Esri ArcGis map control which I want to round around the edges. I am also using Prism4.0/MEF and SL4.
I tried to place it in a border, but that doesn't work (the Esri control is loaded into the MapRegion, in another module):
<Border Grid.Row="2"
Margin="2"
CornerRadius="25">
<ContentControl
prism:RegionManager.RegionName="MapRegion"
VerticalContentAlignment="Stretch"
HorizontalContentAlignment="Stretch">
</ContentControl>
</Border>
UPDATE: Looks like this is not possible. This isn't really a bug with the Map itself, but it kind of is. The Map uses a Canvas inside the Grid "RootElement". This Canvas holds the images for the map. When using a Canvas, it doesn't respect the bounds it's been given. You can reproduce the bug with the following XAML
<Border BorderBrush="Red" BorderThickness="2" CornerRadius="25">
<Grid>
<Grid>
<Canvas>
<Image Source="/Images/MyPicture.png"/>
</Canvas>
</Grid>
</Grid>
</Border>
The best approach is going to be to set an explicit style for the map. With this style any map that is used will have the rounded corners
<Style TargetType="esri:Map">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="esri:Map">
<Border CornerRadius="25" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}">
<Grid>
<Grid x:Name="RootElement" Height="Auto" Width="Auto"/>
<Rectangle x:Name="ZoomBox" Fill="#55FFFFFF" Stroke="Red" StrokeThickness="2" Visibility="Collapsed"/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

WPF DataGridCell Template with TextBlock - Binding?

i replace the ContentPresenter in the DataGridCell's Template with a TextBlock an now i search for the correct Binding to the content.
The normal way is Text="{TemplateBinding Content} for the TextBlock - it doesn't work. Also Text="{Binding RelativeSource={RelativeSource TemplatedParent},Path=Content, Mode=TwoWay}" doesn't work correct.
Any other ideas?
Suppose you have changed the DataGridCell Template to the following
<ControlTemplate TargetType="{x:Type DataGridCell}">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
<TextBlock Text="{Binding}"/>
<!--<ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/> -->
</Border>
</ControlTemplate>
Since you removed the ContentPresenter, the DataGridCell has no way of displaying its Content. It's still there though. The DataGridCell.Content
is a TextBlock containing your original Text and the TextBlock in the Template is another.
So you'll get the correct Text by binding it to the Content.Text property of the TemplatedParent
<TextBlock Text="{Binding RelativeSource={RelativeSource TemplatedParent},
Path=Content.Text}"/>
So, to sum it up. This works
<ControlTemplate TargetType="{x:Type DataGridCell}">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
<TextBlock Text="{Binding RelativeSource={RelativeSource TemplatedParent},
Path=Content.Text}"/>
</Border>
</ControlTemplate>
The data context of the data grid cell should be the data itself. So the binding should simply be:
<TextBlock Text="{Binding}"/>

Silverlight - use a ScrollViewer in a TextBox template

I'm trying to make a TextBox template and I need to include a ScrollViewer in the template - basically I want to add some content (like line numbers) that needs to scroll along with the normal text.
The default template for the TextBox is like this:
<Border x:Name="Border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" CornerRadius="1" Opacity="1">
<Grid>
<Border x:Name="ReadOnlyVisualElement" Background="#5EC9C9C9" Opacity="0"/>
<Border x:Name="MouseOverBorder" BorderBrush="Transparent" BorderThickness="1">
<ScrollViewer x:Name="ContentElement" BorderThickness="0" IsTabStop="False" Padding="{TemplateBinding Padding}"/>
</Border>
</Grid>
</Border>
If I change the ContentElement from ScrollViewer to Border, for example, the TextBox behaves normally - i just lose the scrolling ability.
Now, if I wrap the ContentElement with a ScrollViewer, it no longer displays the caret and selection - if you type, it still gets updated though.
<Border x:Name="Border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" CornerRadius="1" Opacity="1">
<Grid>
<Border x:Name="ReadOnlyVisualElement" Background="#5EC9C9C9" Opacity="0"/>
<Border x:Name="MouseOverBorder" BorderBrush="Transparent" BorderThickness="1">
<ScrollViewer ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto" >
<Border x:Name="ContentElement" BorderThickness="0" Padding="{TemplateBinding Padding}" />
</ScrollViewer>
</Border>
</Grid>
</Border>
Any idea why this happens and how can I fix it?
Just a shot in the dark, as I have not verified...but the control may be looking for a TemplatePart named ContentElement of type ScrollViewer.

Resources