I have a simple grid that displays a portion of an image.
<Grid x:Name="back_side" Margin="-1" RenderTransformOrigin="0.5,0.5" RenderTransform="{Binding ScaleTransformBack}" Width="Auto">
<Image Source="/NameSpace;component/Resources/image.jpg" Stretch="Fill">
<Image.Clip>
<RectangleGeometry Rect="{Binding RectGeo}"/>
</Image.Clip>
</Image>
</Grid>
I have tried binding directly to a RectangleGeometry in code behind as well. The clip doesn't seem to want to work. Any suggestions? Anyone have any experience with binding a clip to an image?
I need to be able to programmatically segment a specific image across a number of controls. Using the clip as the calculated portion for each control to display.
If you want to display only part of your image you can use CroppedBitmap as Image.Source
<Image>
<Image.Source>
<CroppedBitmap Source="/NameSpace;component/Resources/image.jpg" SourceRect="{Binding RectGeo}"/>
</Image.Source>
</Image>
You can bind CroppedBitmap.SourceRect but you need to make sure that RectGeo is of a Int32Rect type
EDIT
Unfortunately if you plan to change SourceRect at runtime this won't work as:
After initialization, property changes are ignored
So what you can do is create custom IValueConverter which will create a CroppedBitmap:
public class CropBitmapConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return new CroppedBitmap(new BitmapImage(new Uri((string)parameter, UriKind.RelativeOrAbsolute)), (Int32Rect)value);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
and use it with your binding:
<Image ... Source="{Binding Path=RectGeo, Converter={StaticResource CropBitmapConverter}, ConverterParameter='pack://application:,,,/NameSpace;component/Resources/image.jpg'}" />
Related
I have a big lists of objects which are binded to a ListBox. In that list box i am displaying the name of a file and a byte array of an image which is coming form WCF. I would display the files in the listbox depending on the scroll postion, so the file which are not visible from that scroll position to be set as Hidden.
I found on the internet a way which might help me but i cannot see a way that this will work.
I found convertors which should help me, and set up that class as a window resource. When I am opening the app all the items are converted to be visible.
This is the class:
class NullVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value == null ? Visibility.Hidden : Visibility.Visible;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return value == null ? Visibility.Visible : Visibility.Hidden;
}
}
In Xaml i setup this class as a window Resource and i binded the functionality to the image and name in the Listbox items
<Window.Resources>
<view:NullVisibilityConverter x:Key="NullToVis"/>
</Window.Resources>
<Image Source="{Binding Path=Image}" Visibility="{Binding Path=Image, Converter={StaticResource NullToVis}}" Height="80" Width="80" Grid.Column="0"/>
<StackPanel Grid.Column="1" Visibility="{Binding Path=Image, Converter={StaticResource NullToVis}}" Orientation="Vertical" Width="80" Height="30">
<TextBlock Text="{Binding Path=Name}" Margin="5,1,0,1"/>
</StackPanel>
Does anyone have any idea how this might work?
I have the problem that I would like to render the contents of a variable (referenced via the expression "Metatag.Configuration[VisualizerCode].Value" in the code below). The variable contains xaml code (as a string), for example the following contents:
<Grid>
<Canvas>
<Border Canvas.Top="0" Canvas.Left="390" Width="50" Height="100" BorderThickness="2" BorderBrush="Black"> </Border>
<Border Canvas.Top="100" Canvas.Left="340" Width="100" Height="50" BorderThickness="2" BorderBrush="Black"> </Border>
</Canvas>
</Grid>
In my application I have a Grid, in which I would like to render the contents of the variable:
<Grid Margin="0,10,0,0" Visibility="Visible">
<ContentControl Content="{Binding Path=Metatag.Configuration[VisualizerCode].Value}">
</ContentControl>
Unfortunately, if I run this, the string (= uninterpreted contents of the variable) is printed as text in the Grid, instead of being interpreted (in which case 2 nice, simple borders should be drawn).
How can I get XAML to interpret the contents of the variable and render it ?
Thanks !
Woelund
You can try using some custom Converter to convert (parse) the string to some instance of the Grid:
public class StringToElementConverter : IValueConverter {
public object Convert(object value, Type targetType, object parameter,
CultureInfo culture){
var pc = new ParserContext();
pc.XmlnsDictionary[""] =
"http://schemas.microsoft.com/winfx/2006/xaml/presentation";
pc.XmlnsDictionary["x"] = "http://schemas.microsoft.com/winfx/2006/xaml";
return XamlReader.Parse(System.Convert.ToString(value), pc);
}
public object ConvertBack(object value, Type targetType, object parameter,
CultureInfo culture){
throw new NotImplementedException();
}
}
Declare the converter as some resource and used for the Binding in XAML code:
<Window.Resources>
<local:StringToElementConverter x:Key="elementConverter"/>
</Window.Resources>
<ContentControl Content="{Binding Metatag.Configuration[VisualizerCode].Value,
Converter={StaticResource elementConverter}}"/>
I hope you know how to declare the prefix local representing the local namespace in which your converter class is declared.
I have a couple of gauges in my app, and I can't figure out how to add a converter to the text binding. I read a couple of guides on msdn but I didn't manage to figure that out (I've been coding for WP8 for just a couple of weeks).
This is is a piece of the gauge:
<gauges:MarkerGaugeIndicator Value="0"
gauges:LinearGaugeRange.IndicatorOffset="35"
x:Name="GaugeBarValore"
IsAnimated="True">
<gauges:MarkerGaugeIndicator.MarkerTemplate>
<DataTemplate>
<Grid Width="73" Height="35" UseLayoutRounding="False" d:LayoutRounding="Auto" Margin="10,-2,0,0">
<TextBlock x:Name="GaugeBarPercent" Text="{Binding}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="20"
FontWeight="Thin" Margin="6,4,32,4" Width="35"/>
<Grid.RenderTransform>
<CompositeTransform Rotation="90" TranslateX="49" TranslateY="12" />
</Grid.RenderTransform>
</Grid>
</DataTemplate>
</gauges:MarkerGaugeIndicator.MarkerTemplate>
</gauges:MarkerGaugeIndicator>
The binding itself works, but I can see a lot of decimal numbers while the value moves from a round value to another.
I want to add a converter like this method:
private String double2String(double valore)
{
return Convert.ToString(Math.Round(valore)) + "%";
}
I just don't know where to put this method and how to add this as a converter inside the binding.
Thank you for your help! :)
Sergio
Create a class to hold your Converter method that implements IValueConverter interface, Example class is bellow. You have to implement method Convert and ConvertBack.
public class DoubleToString : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return Math.Round((double)value).ToString() + "%";
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return double.Parse(value as string);
}
}
then add the namespace to your XAML page.
xmlns:convert="clr-namespace:Your_project_name"
Next add your converter as a Resource type i to your XAML page..
<phone:PhoneApplicationPage.Resources>
<convert:DoubleToString x:Key="DoubleConvert" />
</phone:PhoneApplicationPage.Resources>
The x:Key value is the name we are going to call in our binding statement.
Then perform the data binding. I have a simple slider and a textblock with sliders value bound to the textblocks Text property
<StackPanel>
<Slider Name="slider" Maximum="100" Minimum="0" />
<TextBlock Text="{Binding Value, ElementName=slider, Converter={StaticResource DoubleConvert}}" />
</StackPanel>
Define this converter as a resource in your parent view
<UserControl.Resources>
<local:double2String x:Key="convertDouble" />
</UserControl.Resources>
And add it to the binding
<TextBlock x:Name="GaugeBarPercent" Text="{Binding, Converter={StaticResource convertDouble}}"
Don't forget to import the namespace where the converter is defined to your view
xmlns:local="clr-namespace:YOUR_NAMESPACE"
The easier way is to use StringFormat. Like this:
<Label Text="{Binding Path=SomeProperty, StringFormat='{0:F2}%' }"/>
I've created a DataTemplate for my objects in a ResourceDictionary file. The template is basically an image that is loaded from the disk. Now, what happens is that I want to align the image to a specific point on my Canvas but not by its upper left point but its center point, that's why I want to apply a translate transform for X = -Width / 2 and
Y = -Height / 2 but I don't know how to apply them via the DataTemplate.
Any help will be appreciated, thanks!
Try using databinding on Canvas' the AttachedProperties and an IValueConverter to transform the offsets to whatever you want.
For instance:
class ImageToCanvasConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return -(int)value / 2;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
// Two-way binding not supported
throw new InvalidOperationException();
}
}
<Grid.Resources>
<myAssembly:ImageToCanvasConverter x:Key="imageToCanvasConverter" />
<DataTemplate ...>
<Image Canvas.Left="{Binding Path=Width, Converter={StaticResource imageToCanvasConverter}, Mode=OneTime}"
Canvas.Top="{Binding Path=Height, Converter={StaticResource imageToCanvasConverter}, Mode=OneTime}"
... />
</DataTemplate>
</Grid.Resources>
you can take the advantage of using loaded event on the data template child
Example:
if you are using grid as data template content
<DataTemplate>
<Grid Loaded="Grid_Loaded">
<Image></Image>
</Grid>
</DataTemplate>
you can write the transformation code in the .cs file using sender object.
I'm building a wp7 app in Silverlight. I have some content that gets loaded asynchronously, and messages that indicate that loading is not yet done. I'd like to have the loading messages disappear as soon as the content's list box is not empty. Is it possible to do this just in XAML? Something like binding the Visibility property to StoryListBox.ItemsSource.IsEmpty?
StoryListBox is populated by having its ItemsSource set to an observable collection after the data is available.
<TextBox x:Name="LoadingMessage" Text="Loading..." Grid.Row="0" />
<ProgressBar x:Name="LoadingProgress" IsIndeterminate="True" Style="{StaticResource PerformanceProgressBar}" />
<ListBox x:Name="StoryListBox" Grid.Row="0" />
Update: I tried the following, but it doesn't work:
<StackPanel x:Name="Loading" Grid.Row="0" Visibility="{Binding StoryListBox.ItemsSource.IsEmpty, Converter={StaticResource visibilityConverter}}">
<TextBox Text="Loading..." />
<ProgressBar IsIndeterminate="True" Style="{StaticResource PerformanceProgressBar}" />
</StackPanel>
<ListBox x:Name="StoryListBox" Grid.Row="1" />
The Loading stack panel never collapses.
You seem to have answered your own question. Yes, you can simply bind the Visibility (or Busy/IsBusy on a BusyIndicator control to some attribute of another control).
If the specific property you want to bind to is not a bindable property, simply bind to the other control and customise the converter to get the member property you want. If you have specific code examples, just post them and I can post a more specific solution.
The usual problem is that the types (for visibility) are incompatible with boolean values, so you need to specifier a converter in the binding. Google for Silverlight VisibilityConvertor (they are a dime a dozen). Here is mine:
namespace Common.ValueConverters
{
using System;
using System.Windows;
using System.Windows.Data;
public class VisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value is bool?)
{
if (string.IsNullOrEmpty((string)parameter))
{
return (value as bool?).Value ? Visibility.Visible : Visibility.Collapsed;
}
else
{
return (value as bool?).Value ? Visibility.Collapsed : Visibility.Visible;
}
}
throw new ArgumentException();
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
A use of the converter would look like:
<Grid Visibility="{Binding ShowDualView, Converter={StaticResource VisibilityConverter}}">
But quite frankly you are better of with a BusyIndicator control bound to an IsBusy property:
<Controls:BusyIndicator IsBusy="{Binding IsBusy}">
Just put it around the controls to you want to have hidden by the busy display.