Creating a reflection of a WindowsFormHost in wpf - c#

I am very new to WPF and I am a bit stuck.
I'm trying to create a demo program that displays several embedded win forms applications. I'd like to add a reflection of the form, but most of the existing tutorials I've seen seen for image reflections do not work.
If anyone can point me in the right direction I would really appreciate it.
Here is the relevent XAML - the form control is added to the embedForm stack panel dynamically.
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Border Name="inkBorder" Grid.Row="0" VerticalAlignment="Bottom" Margin="20"
Width="400" Height="500" CornerRadius="5" BorderThickness="4">
<Border.BorderBrush>
<LinearGradientBrush SpreadMethod="Reflect" StartPoint="0,0" EndPoint="0.5,0.5">
<LinearGradientBrush.GradientStops>
<GradientStop Color="Gray" Offset="0" />
<GradientStop Color="#eeeeee" Offset="1" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Border.BorderBrush>
<StackPanel Name="EmbedForm" Height="100" Width="400" ></StackPanel>
</Border>
<Rectangle Grid.Row="1" VerticalAlignment="Top"
Width="{Binding ElementName=inkBorder,Path=ActualWidth}"
Height="{Binding ElementName=inkBorder,Path=ActualHeight}">
<Rectangle.OpacityMask>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0.0" Color="#66000000" />
<GradientStop Offset="1.0" Color="#00000000" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Rectangle.OpacityMask>
<Rectangle.Fill>
<VisualBrush
Visual="{Binding ElementName=inkBorder}">
<VisualBrush.RelativeTransform>
<TransformGroup>
<ScaleTransform ScaleX="1" ScaleY="-1" />
<TranslateTransform Y="1" />
</TransformGroup>
</VisualBrush.RelativeTransform>
</VisualBrush>
</Rectangle.Fill>
</Rectangle>
</Grid>
To clarify the question a bit...
I am mainly looking for a way to apply any visual transformations to controls like the WindowsFormHost and the WebBrowser control.
I've found that even simple transformations do not work with these, and I was wondering if there is any trick to treating these like standard visual elements or if it is a lost cause.

Transformations on WindowsFormsHost or WebBrowser won't work, because these controls don't use the WPF rendering engine, they use GDI+.
As far as I know, the only way to achieve what you want would be to capture the control's content as an image, and manually perform the transformation on the image using GDI+ functions... It's quite easy for a simple reflection, but it can get tricky for other kinds of transformation...

Related

Create borderbrush "around the border path"

I'm trying to create a border with a gradient stroke around the border path, not around the full element but around the border itself.
A simple example of what I do not want is:
<Border BorderThickness="10" Width="100" Height="50">
<Border.BorderBrush>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="White" Offset="0"/>
<GradientStop Color="Black" Offset="0.5"/>
<GradientStop Color="White" Offset="1"/>
</LinearGradientBrush>
</Border.BorderBrush>
</Border>
This creates a border that looks like:
What I to achieve wish is something like the image below. Notice that this achieved by blurring, I rather not do that as that would limit the what can be done - and more importantly: it would either blur all child elements, or I'd lose the ability to walk the visual tree with the border at the expected position. (Border would be a sibbling to its "content")
Dig a bit into shadow of border it looks closer
<Border BorderThickness="5" Width="100" Height="50" CornerRadius="5" BorderBrush="Gray">
<Border.Effect>
<DropShadowEffect BlurRadius="20" Opacity="1" ShadowDepth="1" Color="Black">
</DropShadowEffect>
</Border.Effect>
</Border>
It will give you something like
Alternatively
you can draw Blured dummy border on the same place with the current one (Bind width and height), but lower in the markup, in that case UI will draw dummy border over your container border and you'll see bluring without harming the tree
<Border BorderThickness="0" Width="100" Height="50" CornerRadius="5" BorderBrush="Gray" x:Name="x">
<TextBox Width="70" Height="20">Some data</TextBox>
</Border>
<Border BorderThickness="5" Width="{Binding Width, ElementName=x}" Height="{Binding Height, ElementName=x}" CornerRadius="0" BorderBrush="Black">
<Border.Effect>
<BlurEffect Radius="10"></BlurEffect>
</Border.Effect>
</Border>
If you really want to be able to have a blurred gradient border i think you might have to go with something like this.
Create a trapeze-shape with your gradient:
Then copy this shape 3 times and apply some render-transformations to get the border shape
Apply a Blur Effect on the whole shape
I made all those screenshots directly from the WPF result.

C# Xaml ListBox Template Add in c#

I did some research about the listbox but i didnt understand how to solve my problem.
I have a Listbox in my xaml page and i want to add now a listviewitem using the Template (so i get toggle button and so on) not in xaml and with the help of c#. How do i do this? Thx for your help
<ListBox x:Name="Listbox" Background="Red">
<ListBox.ItemTemplate >
<DataTemplate>
<Grid x:Name="TemplateGrid">
<ToggleSwitch x:Name="Toggle" Foreground="Black">
<ToggleSwitch.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="Black" Offset="0"/>
<GradientStop Color="Black" Offset="1"/>
</LinearGradientBrush>
</ToggleSwitch.Background>
</ToggleSwitch>
<TextBlock HorizontalAlignment="Right" VerticalAlignment="Center" Width="26" x:Name="Text" Foreground="Black">Test</TextBlock>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
The listbox will use the template automatically. From your code, just call Listbox.Items.Add(obj). One thing to note though - in your data template I don't see that you are specifying a datatype for your data template to target, so it will use a generic display by calling ToString() on your object.

How to bind a field to a gauge control?

I've added a WPF gauge control from this class https://github.com/JohanLarsson/GaugeBox but I'm not sure how to wire the control up to a field of type double degreeOutput declared in the code behind.
My aim is to bind degreeOutput to the gauge control and have the values from degreeOutput update the gauge accordingly.
The process I followed in setting up the control is:
1)Add the control to the user control's xaml layout and declare the namespace
xmlns:gauges="clr-namespace:Gauges;assembly=Gauges"
2)Set the value property to Value="{Binding degreeOutput}"
3)Run application, (but the gauge doesn't update in accordance with the
degree readings being output from degreeOutput)
Does anyone know what step I'm missing in binding the control to my degree field?
This is the xaml layout for the guage control:
<gauges:Gauge x:Name="Gauge"
Grid.Row="0"
Margin="13,18,134,134"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Marker="{Binding Marker}"
Maximum="{Binding Max}"
Minimum="{Binding Min}"
Placement="{Binding Placement}"
ShowLabels="{Binding ShowLabels}"
ShowMajorTicks="{Binding ShowTicks}"
ShowTrack="{Binding ShowTrack}"
TickFrequency="{Binding TickFrequency}"
Value="{Binding degreeOutput}" RenderTransformOrigin="0.5,0.5">
<gauges:Gauge.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform Angle="-89.868"/>
<TranslateTransform/>
</TransformGroup>
</gauges:Gauge.RenderTransform>
<gauges:Gauge.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Offset="0.0" Color="Red" />
<GradientStop Offset="0.10" Color="Red" />
<GradientStop Offset="0.10" Color="Green" />
<GradientStop Offset="0.90" Color="Green" />
<GradientStop Offset="0.90" Color="Red" />
<GradientStop Offset="1.0" Color="Red" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</gauges:Gauge.Background>
</gauges:Gauge>
And the code behind where degreeOutput is declared:
private double degreeOutput;
Generally speaking you can't bind to fields in WPF (see the answer to this SO question).
Try changing degreeOutput into a public property. This will be enough to feed the initial value through into the gauge control.
If you also want changes made by the gauge control to feed back into your property then the class containing the property must also implement INotifyPropertyChanged.

Paint a control twice

I'm working on a very eye-candy program and I'm required to add a reflection and a 3D depth to the controls.
On both cases I need to paint the control a couple of times, but with changes:
For the reflection I'll have to repaint the control again at the bottom + flip it.
And as for the 3D depth, it's just a lot of copies behind + to the side.
The question is how can I get the image of the control in order to modify it and paint it below / behind it? Do you have any caveats and warnings / helpful tips regarding such actions? (I've never tried anything similar before).
Many thanks.
In WPF you can use a VisualBrush as the background/fill of another element (such as a Rectangle). This VisualBrush has a Visual property that can be bound to another control in order to mimic its content. Using transforms and alpha masks on this control can help apply reflection-style effects. For example:
<StackPanel Width="200">
<TextBox x:Name="tb">Hello world</TextBox>
<Rectangle Height="40" HorizontalAlignment="Stretch">
<Rectangle.Fill>
<VisualBrush Visual="{Binding ElementName=tb}" />
</Rectangle.Fill>
<Rectangle.RenderTransform>
<ScaleTransform CenterY="20" ScaleY="-1" />
</Rectangle.RenderTransform>
<Rectangle.OpacityMask>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="#00000000" Offset="0" />
<GradientStop Color="#FFFFFFFF" Offset="1" />
</LinearGradientBrush>
</Rectangle.OpacityMask>
</Rectangle>
</StackPanel>

Dynamically load images from database and display in Silverlight 3 image rotator

I have a Silverlight 3 image rotator that displays approx.7 images. You can rotate it back and forth, and it will make the left or right image the selected image. The rotator is using jpg images that resides in an image folder. I would like to dynamically load image strings from the database, since I have hundreds of images available. My question is: How can I load a list or collection based on a query, convert the image strings into Pictures and load them into the rotator dynamically. here is what I have now.
XAML
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vc="clr-namespace:Visifire.Charts;assembly=SLVisifire.Charts"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:CollectionFlow="clr-namespace:CollectionFlow;assembly=CollectionFlow"
x:Class="CollectionFlowSample.MainPage"
d:DesignWidth="640" d:DesignHeight="480" Loaded="UserControl_Loaded" Width="900" Height="800">
<UserControl.Resources>
<DataTemplate x:Key="DataTemplate1">
<Grid RenderTransformOrigin="0.5,0.5">
<Grid.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform Y="100"/>
</TransformGroup>
</Grid.RenderTransform>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="5"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Border Height="180"
HorizontalAlignment="Left" VerticalAlignment="Top"
Width="140" BorderThickness="10" Margin="16,14,0,0"
CornerRadius="2">
<Border.BorderBrush>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="Black" Offset="0"/>
<GradientStop Color="#FF282323" Offset="1"/>
<GradientStop Color="#FF413636" Offset="0.556"/>
<GradientStop Color="#FFCEBABA" Offset="0.83"/>
</LinearGradientBrush>
</Border.BorderBrush>
<Image Source="{Binding Mode=OneWay}" Stretch="Fill" >
<Image.Effect>
<DropShadowEffect ShadowDepth="0" BlurRadius="3" Opacity="0.5"/>
</Image.Effect>
</Image>
</Border>
<Image Source="{Binding Mode=OneWay}" Grid.Row="2" RenderTransformOrigin="0.5,0.5">
<Image.Effect>
<BlurEffect/>
</Image.Effect>
<Image.OpacityMask>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Offset="0.5"/>
<GradientStop Offset="1" Color="#7F000000"/>
</LinearGradientBrush>
</Image.OpacityMask>
<Image.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleY="-1"/>
<SkewTransform AngleX="0" AngleY="0"/>
<RotateTransform Angle="0"/>
<TranslateTransform/>
</TransformGroup>
</Image.RenderTransform>
</Image>
</Grid>
</DataTemplate>
<ItemsPanelTemplate x:Key="ItemsPanelTemplate1">
<CollectionFlow:CollectionFlowPanel ItemHeight="400" ItemWidth="160" FocusedItemOffset="60" UnfocusedItemOffset="40" ItemVisibility="5" RenderTransformOrigin="0.5,0.5"/>
</ItemsPanelTemplate>
</UserControl.Resources>
<Grid x:Name="LayoutRoot">
<Grid.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFA0A0A0" Offset="0"/>
<GradientStop Color="Black" Offset="1"/>
</LinearGradientBrush>
</Grid.Background>
<CollectionFlow:CollectionFlow x:Name="ImageList" ItemTemplate="{StaticResource DataTemplate1}" ItemsPanel="{StaticResource ItemsPanelTemplate1}">
<CollectionFlow:CollectionFlow.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFEAE2E2"/>
<GradientStop Color="#FF0E0101" Offset="1"/>
<GradientStop Color="#FF676464" Offset="0.665"/>
</LinearGradientBrush>
</CollectionFlow:CollectionFlow.Background>
</CollectionFlow:CollectionFlow>
C# code
ImageList.ItemsSource = new string[] {"SampleImages/10019436.jpg","SampleImages/10042172.jpg" etc...
Here is what like to do.....
Query Database get records back and then...
use the conversion function process...
string sPic = (string)emps.Photo.ToString();
EmpPic1.Source = ConvertBase64ToImage(sPic);
public BitmapImage ConvertBase64ToImage(string base64String)
{
//Convert Base64 String to byte[]
byte[] imageBytes = Convert.FromBase64String(base64String);
BitmapImage bi = new BitmapImage();
bi.SetSource(new MemoryStream(imageBytes));
return bi;
}
This is where I like to add the queried images to a collection,and use the technique described above to dispaly them in the image rotator.
Any help would be appreciated.
you need to request data using a web server (through a web service call is a good way of achieving this) this will return the data to your silverlight application, you wont be able to connect to a database directly with silverlight, your service will access the database and it can then return the data to your application to be consumed by the code you discussed above.
Create a web service that returns the image data
add a web reference to your silverlight application that points to your service
use the generated proxy to call the service and return the data to your application
- you could either use the serviceclient of the proxy with an asynchronous call back or forget the proxy and just call the service using webclient
i think its important to understand the client based nature of silverlight, it lives in a sandbox on a remote computer in its most typical use case, so accessing data doesnt use the same approach as say a windows forms application>

Categories