WPF Window Background ImageBrush not tiling - wpf

I have a window with a background image. The image may change at runtime which really should not matter for this.
I want the image to be fixed to the top left (which it is) and not scale (which is also correct. But I need the image to repeat (tile) when the window is made larger than the image. I am doing ...
What am i missing?
TIA

You need to set the TileMode property as well as the Viewport and ViewportUnits:
For example:
<Window.Background>
<ImageBrush ImageSource="myImage.png"
Viewport="0,0,300,300"
ViewportUnits="Absolute"
TileMode="Tile"
Stretch="None"
AlignmentX="Left"
AlignmentY="Top" />
</Window.Background>
Note: the second 2 segments of the Viewport attribute indicate the desired size of each repetition. If you want to display the entire image, these should be the width and height of the image.
Example output:
Edit in response to comments
If you don't know the size of the image to specify in the Viewport property, you can use a Binding with an IValueConverter to calculate it from the image. I am convinced there must be a better way of doing this, but I haven't found one yet!
XAML:
<Window.Resources>
<local:Converter x:Key="Converter" />
</Window.Resources>
<Window.Background>
<ImageBrush ImageSource="myImage.png"
ViewportUnits="Absolute"
TileMode="Tile"
Stretch="None"
AlignmentX="Left"
AlignmentY="Top"
Viewport="{Binding ImageSource, RelativeSource={RelativeSource Self}, Converter={StaticResource Converter}}"/>
</Window.Background>
Value converter:
public class Converter : IValueConverter
{
#region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var source = (ImageSource)value;
return new Rect(0,0,source.Width, source.Height);
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
#endregion
}

If you would like the entire solution in c#
ImageBrush brush = new ImageBrush();
brush.ImageSource = new BitmapImage(new Uri(#"c:\your\image\source.gif"));
brush.TileMode = TileMode.Tile;
brush.ViewportUnits = BrushMappingMode.Absolute;
brush.Viewport = new Rect(0, 0, brush.ImageSource.Width, brush.ImageSource.Height);
MainWindow1.Background = brush;

Related

Set a property in XAML to a function

I need to set the property of cotrol which is a dependent of another property of its parent.
I try to explain better my problem with an example. I want to create a toggle switch button that animates a "slider" element into it. The dimensions of the toggle switch is being defined when the usercontrol is inserted into the application window. I want the slider be sized half larger than the switch case. So if the control is large 100, the slider should be 50, or if large 250, the slider should be 125. Then I need a sort of call to a function or something similar:
<UserControl>
<Border Name="switchCase" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Border Name="slider" Width="**Container.Width/2**" ></Border>
</Border>
</UserControl>
Is there any possibilities to achieve this ??
Thanks in advance
Paolo
Yes you need databinding with a converter, such as the following example
xmlns:conv="clr-namespace:MyConverters.Converters"
.......
<UserControl.Resources>
<conv:WidthConvertercs x:Key="widthConv"></conv:WidthConvertercs>
</UserControl.Resources>
<Border Name="switchCase" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" >
<Border Name="slider" Width="{Binding ElementName=switchCase, Path=ActualWidth, Converter={StaticResource widthConv}}" Background="DarkMagenta"></Border>
</Border>
Your converter class would be
[ValueConversion(typeof(double), typeof(double))]
class WidthConvertercs : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
double withPar = (double)value;
return withPar/2.0;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
I hope this helps
Out of the box it's not supported by XAML. You can only bind to Properties.
You can write a converter which do the calculation (or you can use
MathConverter)
You can do the calculation in the code behind in event
handlers
If you are following the MVVM pattern you can do the
calculation in the ViewModel (altough it will introduce view
related concepts to the ViewModels which is not always good...)
You can write your own Binding extension

Rounded rectangle in Silverlight

I'm trying to create a rectangle in Silverlight where the corners are rounded. However, I do not explicitly specify the width and the height of the rectangle, which means it adapts to the size of the Grid which contains it (the size of the grid depends on the screen resolution amongst other things, and is not known before hand).
I'd like the RadiusX and RadiusY properties to be percentages of the rectangle's width and height respectively. What would be the cleanest way of doing this? Is there a XAML-only way of doing it (without resorting to code-behind)?
Two files below to download I used for testing this http://dl.dropbox.com/u/8679840/SilverlightApplication1.zip
Best way for reuse is to create a Type converter like
<Grid x:Name="LayoutRoot" Background="White">
<Rectangle x:Name="rectangle"
Width="200" Height="200"
RadiusX="{Binding Width, ElementName=rectangle, Converter={StaticResource myConverter}, ConverterParameter=.1}"
RadiusY="{Binding Height, ElementName=rectangle, Converter={StaticResource myConverter}, ConverterParameter=.1}"
/>
</Grid>
and the code behind
namespace SilverlightApplication1
{
public class PercentConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return System.Convert.ToDouble(value) * System.Convert.ToDouble(parameter);
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
While Justin King's answer works if the Width and Height are known before hand, it doesn't work if they're not set, and the parent control dynamically lays the rectangle out. Unfortunately, in Silverlight, you cannot use Binding with Converters on ActualWidth and ActualHeight, as they are calculated properties. What this means is that when ActualWidth and ActualHeight change, a property changed event is not raised internally, so the binding wouldn't propagate the changes to the source.
Essentially, at this point, the only option is to subscribe to the LayoutUpdated event and calculate and set the RadiusX and RadiusY properties in code-behind.

WPF Opacity Mask at fixed location

I need to get rid of a part of a component ( make it totally transparent ) , a small bar at the bottom of it actually.
It's a fixed size something like 25-30px but the problem is this component will be resized a lot so i can't just put an image as opacity mask. ( which will look bad at different sizes )
Even if the component is 300x300 or 1000x200 , i need to get bottom 25px disappear somehow.
I searched about opacity mask&drawing brush but no luck , can't find a way to dock it at the bottom of component.
By the way , not sure if it matters but the component I'm talking about is WPFChromium browser control.
Is there a way to achieve this by opacity mask or something like viewbox etc?
Thanks in advance!
You could use a LinearGradientBrush as OpacityMask for the Control and Bind the Offset to the ActualHeight of the Control and then subtract 25 from the value and divide it by the ActualHeight in order to get the value in %. This should give you a transparent part of 25px at the Bottom
<WebBrowser Name="webBrowser">
<WebBrowser.OpacityMask>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="#FFFF0000"
Offset="{Binding ElementName=webBrowser,
Path=ActualHeight,
Converter={StaticResource OffsetConverter},
ConverterParameter=25}"/>
<GradientStop Color="#00000000"
Offset="{Binding ElementName=webBrowser,
Path=ActualHeight,
Converter={StaticResource OffsetConverter},
ConverterParameter=25}"/>
</LinearGradientBrush>
</WebBrowser.OpacityMask>
</WebBrowser>
The OffsetConverter
public class OffsetConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
double height = (double)value;
double subract = System.Convert.ToDouble(parameter.ToString());
double opacityMaskHeight = height - subract;
return opacityMaskHeight / height;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}

WPF Label adapt FontSize to it's Width and Height

I need to develop a Label control in WPF, on .NET 3.5 and VisualStudio 2010, in which the FontSize will automatically make the text fill the control area.
I don't know if I should create a CustomControl inheriting from Label or if I should create a UserControl which contains a Label control.
I've seen an example here using a ValueConverter, but I'm not understanding its behavior, here: change font size dynamically.
Can anyone give me a clue about that?
Update:
I found the solutiion using the DoubleConverter from the example I've posted before:
The soultion is using a ValueConverter, which I extracted from the example, but added the NumerFormat IFormatProvider to correctly parse "0.1" value, I found that at Decimal d1 = Decimal.Parse("0.1"); // = 1?!?:
[ValueConversion(typeof(object), typeof(double))]
public class DoubleConverter : IValueConverter
{
public object Convert(object value, Type targetType,
object parameter, CultureInfo culture)
{
double dblValue = (double)value;
double scale = Double.Parse(((string)parameter), System.Globalization.CultureInfo.InvariantCulture.NumberFormat);
return dblValue * scale;
}
public object ConvertBack(object value, Type targetType,
object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Then, you have to instantiate in XAML the DoubleConverter, and specify the binding in the FonSize Property:
<UserControl x:Class="<Namespace>.LabelAutoFontSize"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:me="clr-namespace:<Namespace>"
mc:Ignorable="d"
d:DesignHeight="60" d:DesignWidth="278">
<UserControl.Resources>
<me:DoubleConverter x:Key="doubleConverter" />
</UserControl.Resources>
<Grid>
<Label
x:Name="lbl"
FontSize="{
Binding Path=Width,
RelativeSource={RelativeSource AncestorType={x:Type UserControl}},
Converter={StaticResource doubleConverter},
ConverterParameter=0.116}"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
Content="LabelAutoFontSize"
d:LayoutOverrides="Width"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center" />
</Grid>
</UserControl>
An important point is that the value for ConverterParameter depends absolutely from the font assigned. Each font may need a different value and you have to "play around" to get the correct value to fit exactly.
<Viewbox>
<TextBlock>asd</TextBlock>
</Viewbox>
Also does the job.

WPF Custom Control with Image.

I am quite new to WPF/XAML and I am currently facing a problem.
I have a solution with two projects in it, the first project is a Custom Control Library with a custom Window form control inside. The second project is a WPF application using my custom window form.
All work fine except for the form Icon. In the WPF application project I set my window icon property to /ProjectTwoNameSpace;component/Resources/Images/Film.ico, and in the WPF custom control I try to show that image that way :
<Image Grid.Column="0" Margin="3" Width="27" Height="27">
<Image.Source>
<BitmapImage UriSource="{Binding Path=Icon}" />
</Image.Source>
</Image>
But it doesn't work, I get a error at runtime saying that the property UriSource or StreamSource must be set for my <Image> tag.
Anyone can help me ? I think it's jsut a WPF newbie problem.
The UriSource property of a BitmapImage cannot be set as you have shown because it is of type Uri and you are trying to set it to a string. I'd say the easiest way to accomplish what you're doing is to bind your Image.Source to Icon, and then convert the string to a bitmap Image object. Assuming your control is in a window, this would look something like this
<Window.Resources>
<converters:StringToBitmapImageConverter x:Key="stringToBitmapImageConverter" />
</Window.Resources>
...
<Image Grid.Column="0" Margin="3" Width="27" Height="27"
Source="{Binding Path=Icon, Converter={StaticResource stringToBitmapImageConverter}}">
</Image>
And then the converter would look like:
class StringToBitmapImageConverter: IValueConverter
{
#region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
BitmapImage image = new BitmapImage();
image.BeginInit();
image.UriSource = new Uri(value as string);
image.EndInit();
return image;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
#endregion
}

Resources