How bind control property to a another window property? - c#

I have a window, in which a have a rectangle. I want its fill to be a gradientstop for another rectangle fill, but on different window. The "source" window is defined as:
<Window x:Class="WPF1.ColorSelectorWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:my="clr-namespace:WPF1"
x:Name="colorSelectorWindow"
Title="ColorSelectorWindow" Height="281" Width="540">
There's a rectangle
<Rectangle HorizontalAlignment="Left" Margin="40,120,0,41" Stroke="Black" Width="100" Name="ColorPicker">
<Rectangle.Fill>
<SolidColorBrush>
<SolidColorBrush.Color>
...
</SolidColorBrush.Color>
</SolidColorBrush>
</Rectangle.Fill>
</Rectangle>
and a property:
public partial class ColorSelectorWindow : Window
{
public Brush SelectedBrush
{
get
{
return ColorPicker.Fill;
}
}
}
Now, in the target window, I define a rectangle:
<Rectangle Height="213" HorizontalAlignment="Left" Margin="27,8,0,0" Name="rectangle1" VerticalAlignment="Top" Width="25" Grid.Row="1">
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
<GradientStop Offset="0" Color="Blue" />
<GradientStop Offset="1" Color="{Binding ElementName=colorWindowSelector, Path=SelectedBrush, Converter={StaticResource BrushToColorConverter}}" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
where BrushToColorConverter converts Brush to Color. This isn't working and I don't know why, it seems I have a problem with addressing that "source" window.. I'm building it in the target window constructor:
public MainWindow()
{
colorWindow = new ColorSelectorWindow();
colorWindow.Name = "colorWindowSelector";
colorWindow.Hide();
InitializeComponent();
}
I'm only hiding and showing it, not closing for sure. How to bind it properly?

You need to have property exposed SelectedBrush on your MainWindow and you just need to bind to the color of this Brush using RelativeSource. So, this will do for you -
<Rectangle Height="213" HorizontalAlignment="Left" Margin="27,8,0,0" Name="rectangle1" VerticalAlignment="Top" Width="25" Grid.Row="1">
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
<GradientStop Offset="0" Color="Blue" />
<GradientStop Offset="1" Color="{Binding Path=Owner.SelectedBrush, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType =Window} Converter={StaticResource BrushToColorConverter}}" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
But make sure while creating the window, you set its owner to be MainWindow -
public MainWindow()
{
InitializeComponent();
colorWindow = new ColorSelectorWindow();
colorWindow.Name = "colorWindowSelector";
colorWindow.Owner = this;
colorWindow.Hide();
}

Related

WPF change color of Rectangle Fill in code

Hey all I am new at WPF's and am in need of changing the color of a Rectangle fill in a WPF.
Currently I have this:
<Rectangle Fill="{Binding aColor}" RadiusY="5" RadiusX="5">
<Rectangle.Effect>
<DropShadowEffect ShadowDepth="0"/>
</Rectangle.Effect>
</Rectangle>
I am not sure how to go about using that binding above within code.
Any help would be great!
Fill property is of type Brush , so you cant bind color directly,
Do something like this,
<Rectangle Width="100"
Height="100">
<Rectangle.Fill>
<SolidColorBrush Color="{Binding color}"/>
</Rectangle.Fill>
</Rectangle>
Otherway is you can implement your Color-To-Brush converter. Like this
Got it!
C#:
System.Drawing.Color c = ColorTranslator.FromHtml("#FFFFFF");
System.Windows.Media.Color color = System.Windows.Media.Color.FromRgb(c.R, c.G, c.B);
aColor.Color = color;
XAML:
<Rectangle RadiusY="5" RadiusX="5">
<Rectangle.Fill>
<SolidColorBrush x:Name="aColor"/>
</Rectangle.Fill>
<Rectangle.Effect>
<DropShadowEffect ShadowDepth="0"/>
</Rectangle.Effect>
</Rectangle>

How to name a WPF control for easier coding?

When adding multiple comboxbox controls, after doubl clicking the item to modify the code, VS 2013 uses a generic naming scheme which makes it hard to keep the code straight. For example, ComboBox_SelectionChanged and ComboBox_SelectionChanged_1.
How do I rename a WPF control to make the CS easier to keep track of?
(Hopefully this makes sense and that I'm using the correct terminology. Let me know if this needs clarification.)
CS Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace hero_workshop
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void ComboBox_SelectionChanged_1(object sender, SelectionChangedEventArgs e)
{
}
private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
}
}
}
WPF Code:
<Window x:Class="hero_workshop.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Hero Workshop" Height="768" Width="1366">
<Grid>
<Menu IsMainMenu="True" Margin="0,0,0,704" Background="White">
<MenuItem Header="_File" />
<MenuItem Header="_Edit" />
<MenuItem Header="_View" />
<MenuItem Header="_Window" />
<MenuItem Header="_Help" />
</Menu>
<TabControl HorizontalAlignment="Left" Height="714" Margin="0,23,0,0" VerticalAlignment="Top" Width="868">
<TabItem Header="Chracter">
<TabItem.Background>
<LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="#FFF0F0F0" Offset="0"/>
<GradientStop Color="White" Offset="1"/>
</LinearGradientBrush>
</TabItem.Background>
<Grid Background="White">
<TextBlock HorizontalAlignment="Left" Margin="10,10,0,0" TextWrapping="Wrap" Text="Character Name" VerticalAlignment="Top"/>
<TextBox HorizontalAlignment="Left" Height="23" Margin="107,7,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120" TextChanged="TextBox_TextChanged"/>
<TextBlock HorizontalAlignment="Left" Margin="10,36,0,0" TextWrapping="Wrap" Text="Race" VerticalAlignment="Top" RenderTransformOrigin="-0.621,-2.567"/>
<ComboBox x:Name="race_dropdown" HorizontalAlignment="Left" Margin="107,36,0,0" VerticalAlignment="Top" Width="120" SelectionChanged="ComboBox_SelectionChanged_1"/>
<TextBlock HorizontalAlignment="Left" Margin="317,13,0,0" TextWrapping="Wrap" Text="Alignment" VerticalAlignment="Top"/>
<ComboBox HorizontalAlignment="Left" Margin="388,13,0,0" VerticalAlignment="Top" Width="155" SelectionChanged="ComboBox_SelectionChanged"/>
</Grid>
</TabItem>
<TabItem Header="Skills & Feats">
<TabItem.Background>
<LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="#FFF0F0F0" Offset="0"/>
<GradientStop Color="White" Offset="1"/>
</LinearGradientBrush>
</TabItem.Background>
<Grid Background="White"/>
</TabItem>
<TabItem Header="Weapons & Armor">
<TabItem.Background>
<LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="#FFF0F0F0" Offset="0"/>
<GradientStop Color="White" Offset="1"/>
</LinearGradientBrush>
</TabItem.Background>
<Grid Background="White"/>
</TabItem>
<TabItem Header="Equipment">
<TabItem.Background>
<LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="#FFF0F0F0" Offset="0"/>
<GradientStop Color="White" Offset="1"/>
</LinearGradientBrush>
</TabItem.Background>
<Grid Background="White"/>
</TabItem>
<TabItem Header="Background">
<TabItem.Background>
<LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="#FFF0F0F0" Offset="0"/>
<GradientStop Color="White" Offset="1"/>
</LinearGradientBrush>
</TabItem.Background>
<Grid Background="White"/>
</TabItem>
</TabControl>
<ScrollViewer HorizontalAlignment="Left" Height="689" Margin="873,38,0,0" VerticalAlignment="Top" Width="475"/>
</Grid>
</Window>
Scenario 1: Event handler does not exist
You can influence the naming of your code behind event handler by giving your control a name with the x:name extension property. If you have set the name and double click your control you will get a named event handler like NameOfControl_SelectionChanged.
Scenario 2: Event handler does exist
If you already have created the event handler in your code behind file you have to rename both, the event handler in your code behind and the associated xaml property (SelectionChanged="...") manually.
It's not actually your ComboBox controls that are named "ComboBox_SelectionChanged_1" and "ComboBox_SelectionChanged". The first combobox' name (x:Name) is "race_dropdown" and the second doesn't have a name (UI controls don't need explicit names in WPF).
"ComboBox_SelectionChanged(_1)" are just the default names of the methods that handle the comboboxes' SelectionChanged events. If you give a combobox a name (e.g. x:Name="asdf") before you double-click it, you will get a slighly better event handler name (e.g. "asdf_SelectionChanged").
Now, to answer your question: You can always change the names later on by renaming the method in the code-behind (CS code) and type the same name in the SelectionChanged property in xaml (WPF code).

ComboBox avoid popup close

I am trying to make a custom color picker which inherit from ComboBox.
This is the screenshot.
As you can see, it's just a very normal color picker interface.
So far, almost everything is fine except the problem I write in the screenshot.
I can drag the spectrum slider, RGBA sliders and click those 2 buttons without problem.
If I click on empty space inside the ComboBoxItem, the popup disppears, this is also the behavior I need and it works.
Here are the codes of the canvas area.
XAML
<Canvas x:Name="colorPlatte" Width="175" Height="150" Grid.Row="0" Grid.Column="0" Margin="4" MouseLeftButtonDown="colorPlatte_MouseLeftButtonDown" MouseLeftButtonUp="colorPlatte_MouseLeftButtonUp" MouseMove="colorPlatte_MouseMove">
<Rectangle x:Name="ColorShadingRectangle"
Height="{Binding ElementName=colorPlatte, Path=Height}"
Width="{Binding ElementName=colorPlatte, Path=Width}"
Fill="{Binding ElementName=sliderSpectrum, Path=SelectedColor, Converter={StaticResource ColorToSolidBrush}}"/>
<Rectangle x:Name="WhiteGradient" Width="{Binding ElementName=colorPlatte,Path=Width}" Height="{Binding ElementName=colorPlatte,Path=Height}">
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
<GradientStop Offset="0" Color="#ffffffff" />
<GradientStop Offset="1" Color="Transparent" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Rectangle x:Name="BlackGradient" Width="{Binding ElementName=colorPlatte,Path=Width}" Height="{Binding ElementName=colorPlatte,Path=Height}">
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0,1" EndPoint="0, 0">
<GradientStop Offset="0" Color="#ff000000" />
<GradientStop Offset="1" Color="#00000000" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Canvas x:Name="colorSelector" Width="12" Height="12" IsHitTestVisible="False">
<Ellipse Width="12" Height="12" StrokeThickness="3" Stroke="#FFFFFFFF" IsHitTestVisible="False" />
<Ellipse Width="12" Height="12" StrokeThickness="1" Stroke="#FF000000" IsHitTestVisible="False" />
</Canvas>
</Canvas>
Code-behind related to the canvas
private void colorPlatte_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Point p = e.GetPosition(colorPlatte);
UpdateColorSelectorPosColor(p);
colorPlatte.CaptureMouse();
}
private void colorPlatte_MouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
Point p = e.GetPosition(colorPlatte);
UpdateColorSelectorPosColor(p);
Mouse.Synchronize();
}
}
private void colorPlatte_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
colorPlatte.ReleaseMouseCapture();
}
So, how should I prevent the popup close after user drags the color selector?
Thanks.
Edit : 12/6
Sorry for not descript my question clearly and miss lead you, the previous screenshot was taken in design mode directly and might ignore too much.
I should not say inherit from ComboBox, the ColorPicker is actually an UserControl, and I place it in baseComboBoxItem(inherit from ComboBoxItem) which under a baseComboBox(inherit from ComboBox)
When user click the ComboBox, only one item in popup(the ColorPicker) for user to choose color.
But if user drag the color selector(please refer to previous screenshot), it cause the ComboBox popup(dropdown?) closed automatically.
My question is how should I do to stay the popup open after user drag the color selector(after user trigger MouseLeftButtonUp event)?
I think that if you want to do that (and use a combobox) you have to set the whole template of the combobox (described here), and in the popup set StayOpen to True.
But, as HighCore commented, you don't really need a combobx.
You should have a ToggleButton, and When it's Checked set the canvas visibility to visible, and when it's not checked set the canvas visibility to collapsed

Creating a reflection of a WindowsFormHost in wpf

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...

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