Data Triggers: Hide placeholder if data is available - xaml

Currently I have two images: placeholder image, real image. I want to hide the placeholder image if a thumbnail path for the real image is available. Therefore I thought I could use Data Triggers:
<Image x:Name="placeholder" Aspect="AspectFit" HorizontalOptions="Center" WidthRequest="60" IsVisible="False">
<Image.Triggers>
<DataTrigger TargetType="Image"
Binding="{Binding ThumbnailFilePath}"
Value="{x:Null}">
<Setter Property="IsVisible" Value="True" />
</DataTrigger>
<DataTrigger TargetType="Image"
Binding="{Binding ThumbnailFilePath, Path=Text.Length}"
Value="0">
<Setter Property="IsVisible" Value="True" />
</DataTrigger>
</Image.Triggers>
</Image>
<Image x:Name="preview" Aspect="AspectFit" HorizontalOptions="Center" WidthRequest="60" Source="{Binding ThumbnailFilePath, Converter ={StaticResource ImageSourceConverter}}"/>
If I do this some items in my list view have no image at all (ThumbnailFilePath = null;). For some the thumbnail is shown, for some the placeholder. The source for the placeholder is set in code, because there are some conditions to check. Through scrolling in the list view (items get out of sight and then back in), the placeholder is then shown.
If the path is updated the two images should be visible accordingly:
ThumbnailFilePath = null;
ThumbnailFilepath = "path/to/file.jpg";
Desired action: Placeholder should disappear, thumbnail should be shown.
ThumbnailFilePath = "old/path/to/file.jpg";
ThumbnailFilepath = "path/to/file.jpg";
Desired action: Placeholder should stay hidden, new thumbnail should be shown.
ThumbnailFilePath = "path/to/file.jpg";
ThumbnailFilepath = null;
Desired action: Placeholder should be visisble, thumbnail should be hidden.
Can this be managed with data trigger? How?
I tried to set the visibility through code (code behind file), but the item in the list view is not updated (placeholder is shown, despite a thumbnail is available, only scrolling in the list brings the thumbnail to the front).
Furthermore, I use the placeholder because when I have a binding and then I change the source of the image in code, the binding is gone ...

Now I use View-To-View Bindings:
<Image x:Name="placeholder"
BindingContext="{x:Reference Name=preview}"
Aspect="AspectFit"
HorizontalOptions="Center"
WidthRequest="60"
IsVisible="{Binding Path=Source, Converter ={StaticResource IsNullConverter}">
<Image x:Name="preview"
Aspect="AspectFit"
HorizontalOptions="Center"
WidthRequest="60"
Source="{Binding ThumbnailFilePath, Converter ={StaticResource ImageSourceConverter}}"/>
The above seems to work. I also had to remove all manual settings of IsVisible in code.
Here is the IValueConverter I used:
class IsNullOrEmptyConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is string)
return string.IsNullOrEmpty((string)value);
return (value == null);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new InvalidOperationException("IsNullOrEmptyConverter can only be used one way.");
}
}

Related

How to bind InkCanvas height and width to an image

I have an Image control in a Grid that is displayed when the user clicks on an image in a list. I want to add an InkCanvas control directly on top of the Image control so the user can draw on it.
However, it seems like the height and width of the InkCanvas is not being bound correctly to the image and I am able to draw outside the image. What else do I need to do?
My XAML code:
<Grid>
<Image x:Name="result_img" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<InkCanvas x:Name="inkCanvas" x:Load="False" Height="{x:Bind result_img.ActualHeight}" Width="{x:Bind result_img.ActualWidth}"/>
</Grid>
Code-behind (C++/CX):
void MyGui::test::ListView_ItemClick(Platform::Object^ sender, Windows::UI::Xaml::Controls::ItemClickEventArgs^ e)
{
this->FindName("inkCanvas");
inkCanvas->InkPresenter->InputDeviceTypes = CoreInputDeviceTypes::Mouse;
}
Any help would be much appreciated!
If you want to use element-to-element binding,you should use the ElementName property.The ElementName is the name of the control you want to bind and the Path is the property of the control you want to bind.
<Image x:Name="result_img" VerticalAlignment="Center" HorizontalAlignment="Center" Width="300" Height="400" />
<InkCanvas x:Name="inkCanvas" x:Load="False" Height="{Binding ElementName=result_img, Path=ActualHeight}" Width="{Binding ElementName=result_img, Path=ActualWidth}"/>

Xamarin Forms - adding the calling object as a parameter on a tap gesture recognizer

What is the correct syntax for adding the image in the XAML below as the parameter on the Command?
<ffimageloading:CachedImage Source="{Binding Source}" Aspect="AspectFit" CacheType="Memory" Opacity="2" x:Name="smallImage" >
<Image.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding Path=BindingContext.SetImageCommand, Source={x:Reference this}}"
CommandParameter="{Binding smallImage}" />
</Image.GestureRecognizers>
</ffimageloading:CachedImage>
And the command code it's bound to (CustomCachedImage is just a class derived from a cached image, with an imageName field added)
There will be multiple instances of the calling image as it is in a data template as part of an image slider, so I can't just get the control by name I have to make sure it is the calling control being passed.
public ICommand SetImageCommand
{
get
{
return new Command<CustomCachedImage>((_image) =>
{
string imgName = _image.ImageName;
SetImg(imgName);
});
}
}
changed "{Binding smallImage}" to "{Binding .}" and I got what I needed

how to put images on tabs (pivots) in windows 10 app

I have read most of the Windows 10 UI design guidelines and here are some pictures of examples of a pivot navigation that is essentially a tab navigation with images: https://msdn.microsoft.com/en-us/library/windows/apps/dn997788.aspx#examples
I was unable to find out how to put images on these tabes (pivotitems).
<Pivot x:Name="mainTabs">
<PivotItem x:Name="Header1" Header="Header1" Background="{x:Null}" Foreground="{x:Null}"/>
<PivotItem x:Name="Header2" Header="Header2"></PivotItem>
<PivotItem x:Name="Header3" Header="Header3"></PivotItem>
<PivotItem x:Name="Header4" Header="Header4"></PivotItem>
<PivotItem x:Name="Header5" Header="Header5"></PivotItem>
</Pivot>
HeaderTemplate works OK for replacing text with pictures but then text is missing, and I would like to keep the text like shown in Windows 10 UI guidelines.
<Pivot x:Name="mainTabs">
<Pivot.HeaderTemplate>
<DataTemplate>
<Image Source="{Binding}"></Image>
</DataTemplate>
</Pivot.HeaderTemplate>
<PivotItem x:Name="Header1" Header="Assets/play1.png"></PivotItem>
<PivotItem x:Name="Header2" Header="Assets/play2.png"></PivotItem>
</Pivot>
Nokia Developer website had some really great article about how to make a tabbed pivot headers like official Instagram or Twitter app in Windows Phone.However , that article is not available for now because Microsoft decided to ignore all of Nokia Developer content , unfortunately.
I researched a bit and found this article instead
http://depblog.weblogs.us/2013/08/29/twitterate-your-windows-phone-app/
PivotItem headers' are being used in PivotHeaderTemplate AFAIR.Basically you can follow the article above or just change your Pivot's HeaderTemplate.
Write a converter that converts your Header property to Text and returns it.
public class ImageToTextConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
var sent = value as string;
switch(sent)
{
case "Assets/play1.png":
return "Play 1 Header";
case "Assets/play2.png":
return "Play 2 Header";
default:
return string.Empty;
}
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
Add this converter's namespace to your XAML and define it in your Resources.Then change your template as
<DataTemplate>
<StackPanel>
<Image Source="{Binding}"></Image>
<TextBlock Text="{Binding Source='',Converter={StaticResource ImageToTextConverter}}" />
</StackPanel>
</DataTemplate>
I know this post is old and no one likes to kick a dead horse, but I figured I might share my solution that doesn't rely on a value converter and allows you to simply set an image with text. Just for anyone who is looking to add images or anything to a pivot item since there does not seam to be a simple solution out there.
Add a stack panel to the pivot item header with image and text. That's it.
<Pivot x:Name="Tabs" Grid.Row="1" Grid.Column="0" >
<PivotItem>
<PivotItem.Header>
<StackPanel VerticalAlignment="Top">
<Image Width="25" Height="25" Source="../Assets/Home.png"/>
<TextBlock Text="Home Tab"/>
</StackPanel>
</PivotItem.Header>
<Grid>
<TextBlock Text="asdfasfasdfasdfasdf"/>
</Grid>
</PivotItem>
<PivotItem>
<PivotItem.Header>
<StackPanel VerticalAlignment="Top">
<Image Width="25" Height="25" Source="../Assets/Schedule.png"/>
<TextBlock Text="Home Tab"/>
</StackPanel>
</PivotItem.Header>
<Grid>
<TextBlock Text="134123475"/>
</Grid>
</PivotItem>
</Pivot>

Is it possible to switch transformations on and off via binding in xaml?

I want to activate transformations via checkboxes.
In my sample I have two checkboxes, which should swap the text in a label in x or y direction respectively.
Is this possible without code behind?
Here is my xaml so far:
<Window x:Class="WpfVideoTest.InversionTestWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="InversionTestWindow" Height="300" Width="300">
<DockPanel>
<CheckBox DockPanel.Dock="Bottom" IsChecked="{Binding InvertX}">Invert X</CheckBox>
<CheckBox DockPanel.Dock="Bottom" IsChecked="{Binding InvertY}">Invert Y</CheckBox>
<Label Content="Text to invert" FontSize="40" x:Name="TextToInvert">
<Label.RenderTransform>
<TransformGroup>
<!-- transformations to swap in x direction -->
<ScaleTransform ScaleX="-1" />
<TranslateTransform X="{Binding ActualWidth, ElementName=TextToInvert}" />
<!-- transformations to swap in y direction -->
<ScaleTransform ScaleY="-1" />
<TranslateTransform Y="{Binding ActualHeight, ElementName=TextToInvert}" />
</TransformGroup>
</Label.RenderTransform>
</Label>
</DockPanel>
You'd need to use a Converter or a MultiConverter. Yes, it is code, but it's the orderly way code is added to bindings in WPF. Conceptually, you have a situation where you want the value applied to a transform to be dependent on some other value, and the transform classes themselves don't have that functionality.
This is what the converter might look like. It expects three values where the first is a bool.
public class TernaryConditionalMultiConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (values.Length >= 3 && values[0] is bool)
{
return (bool)values[0] ? values[1] : values[2];
}
return null;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
You'd use it like this:
<ScaleTransform>
<ScaleTransform.ScaleX>
<MultiBinding Converter="{StaticResource TernaryConditionalConverter}">
<Binding Path="InvertX" />
<Binding Source="{StaticResource PositiveOne}" />
<Binding Source="{StaticResource NegativeOne}" />
</MultiBinding>
</ScaleTransform.ScaleX>
</ScaleTransform>
where PositiveOne and NegativeOne have been defined as resources somewhere such as:
<sys:Double x:Key="PositiveOne">1</sys:Double>

xaml define color based on another color

I am learning WinRT, and i define a custom theme for my program, including overwriting some of the default colors
Currently i do something like this in my App.xaml
<Application>
<Application.Resource>
<ResourceDictionary>
...
<Color x:Key="PrimaryColor">#FF0055A3</Color>
<Color x:Key="PrimaryColorHighlighShade">#FF1263B0</Color>
<Color x:Key="PrimaryColorClickShade">#FF2674BD</Color>
...
<SolidColorBrush x:Key="SliderTrackDecreaseBackgroundThemeBrush" Color="{StaticResoruce PrimaryColor}" />
<SolidColorBrush x:Key="SliderTrackDecreasePointerOverBackgroundThemeBrush" Color="{StaticResoruce PrimaryColorHighlighShade}" />
<SolidColorBrush x:Key="SliderTrackDecreasePressedBackgroundThemeBrush" Color="{StaticResoruce PrimaryColorClickShade}" />
...
</ResourceDictionary>
</Application.Resource>
To Get the Highlight shade and ClickShade, i open up photoshop, goto the HSB Slider, and move the S Down and the B up, but i was wondering if i could do this in XAML, so that all i had to do what change the PrimaryColor, and the other colors, where adjusted accordingly.
You can bind to a static resource (see Is it possible to supply a type converter for a static resource in WPF?) and use a value converter to construct a new color based on the color you provide.
Edit:
Here is some code to explain:
The value converter code (for simplicity I always just add red, you can do more complex calculations as you like):
class ColorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value is Color)
{
var theColor = Color.Add((Color)value, Color.FromArgb(255,255,0,0));
return theColor;
}
else
{
return null;
}
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
My App.Xaml looks like this:
<Application x:Class="SO_15979100.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:local="clr-namespace:SO_15979100"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
<Color x:Key="PrimaryColor">#FF0055A3</Color>
<local:ColorConverter x:Key="MyConverter" />
<SolidColorBrush x:Key="PrimaryColorBrush" Color="{StaticResource PrimaryColor}" />
<SolidColorBrush x:Key="ConvertedPrimaryColorBrush" Color="{Binding Source={StaticResource PrimaryColor}, Converter={StaticResource MyConverter}}" />
</Application.Resources>
</Application>
Note that I've included a local namespace to have the converter at hand.
My main window is defined like this:
<Window x:Class="SO_15979100.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Rectangle Grid.Column="0" Fill="{StaticResource PrimaryColorBrush}" />
<Rectangle Grid.Column="1" Fill="{StaticResource ConvertedPrimaryColorBrush}" />
</Grid>
</Window>
The rectangle on the left is your color, the one on the right is pink.
You don't need to use Photoshop to change the colorspaces. Both Visual Studio 2012 and Expression Blend have RGB, HSB, HLS and CYMK colorspace tools.
In your Resource dictionary, select the SolidColorBrush.
IN the property Grid, click the color item.
In the dropdown, select the "Edit Resource".
Here's the trick. Click the R, G or B letters (the ones with the underlines) in the Resource dialog. That causes a menu to appear in the Visual studio editor. Pick your new colorspace.
Choose another colorspace (HSB in your example). Then use the dialog to change the Saturation or Brightness values.
Finally, click the OK button, the color value is modified in the Resource Dictionary.