The Need
I'm setting this in a Data Template.. What I want to do is display a different icon per Hardware type with one special exception. The 3 different Icons I will be using are; Shop, OutlineStar, and OtherUser. All Registers will have the Shop Icon, All Servers will have the OutlineStar, and all display boards will have the OtherUser icon.
The Exception
In some cases a register can also be a server, so I would want to switch the Icon to Outline Star in that case.
The Code
<DataTemplate x:Key="ZoomedInTemp"
x:DataType="DeviceMenu">
<Grid>
<StackPanel Orientation="Vertical" Padding="5">
<TextBlock Text="{x:Bind FacilityName}" />
<StackPanel Orientation="Horizontal">
<SymbolIcon Symbol="Shop" Margin="0,5,12,0"/>
<TextBlock Text="{x:Bind Hardware}" />
<TextBlock Text="{x:Bind HostName}" Margin="10,0,0,0"/>
</StackPanel>
</StackPanel>
</Grid>
</DataTemplate>
You can use Converter to get the desired symbol and place the logic of getting the symbol based on Hardware in the converter.
Converter
public class SymbolConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
// value is Hardware
// Logic to return symbol
//retun Symbol.OutlineStar
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
XAML to use this converter
<DataTemplate x:Key="ZoomedInTemp"
x:DataType="DeviceMenu">
<Grid>
<StackPanel Orientation="Vertical" Padding="5">
<TextBlock Text="{x:Bind FacilityName}" />
<StackPanel Orientation="Horizontal">
<SymbolIcon Symbol="{x:Bind Hardware, Converter={StaticResource SymbolConverter}}" Margin="0,5,12,0"/>
<TextBlock Text="{x:Bind Hardware}" />
<TextBlock Text="{x:Bind HostName}" Margin="10,0,0,0"/>
</StackPanel>
</StackPanel>
</Grid>
</DataTemplate>
You will have to add this converter to the page/app level resource.
I am not sure what you will need to decide the Symbol, however, if you need something else also then you can pass that in ConverterParameter.
Related
I'm developing a Windows Phone 8.1 App. In the app I'm parsing a Json data. From the parsed data, I'm populating a GridView. The JsonData consists of temperature in Kelvin. But I want to change the temperature in Celsius while binding the data in the TextBlock.
Here's the Code in XAML
<StackPanel>
<TextBlock x:Name="tblk1" FontSize="20" />
<TextBlock x:Name="tblk2" FontSize="20" Margin="0,5,0,0"/>
<TextBlock x:Name="tblk3" FontSize="20" Margin="0,5,0,0"/>
<ScrollViewer VerticalScrollBarVisibility="Visible" VerticalScrollMode="Enabled" >
<GridView x:Name="tempList" ItemsSource="{Binding}">
<GridView.ItemTemplate>
<DataTemplate>
<StackPanel Margin="10" Background="DarkGreen">
<StackPanel Margin="5">
<TextBlock Text="{Binding dt}" FontSize="15" />
<TextBlock Text="{Binding temp.day}" FontSize="15" />
<TextBlock Text="{Binding temp.min}" FontSize="15" />
<TextBlock Text="{Binding temp.max}" FontSize="15" />
</StackPanel>
</StackPanel>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
</ScrollViewer>
</StackPanel>
And here's code from the C#
protected override void OnNavigatedTo(NavigationEventArgs e)
{
RootObject obj = JsonConvert.DeserializeObject<RootObject>(MainPage.jsonReturn);
tblk1.Text = obj.city.name;
tblk2.Text = obj.cod;
tblk3.Text = obj.message.ToString();
tempList.DataContext = null;
tempList.DataContext = obj.list;
}
In the output, Here the min and max temp is shown in Kelvin. How do I show it in Celsius?
PS There's no any way to change the Incoming JsonData in Celsius. It
has to changed in runtime.
To answer your specific question, it sounds like you want to use a converter with the binding. E.g.:
class KelvinToCelsiusConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return (double)value - 273.15;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return (double)value + 273.15;
}
}
(Strictly speaking the ConvertBack() method could be left unimplemented, i.e. just throw new NotImplementedException();, but with the above it would also allow for e.g. editable TextBox bindings).
You could then use the above like this, for example:
<TextBlock Text="{Binding Path=temp.day, Converter={StaticResource kelvinToCelsiusConverter1}}" FontSize="15" />
…where you have of course declared the static resource in question, e.g.:
<GridView.Resources>
<local:KelvinToCelsiusConverter x:Key="kelvinToCelsiusConverter1" />
</GridView.Resources>
(I assume here, of course, that you have declared the KelvinToCelsiusConverter class in the namespace which is declared in your XAML as local. Lacking a good, minimal, complete code example, it's impossible to know for sure what all of the above should look like, including namespace declarations).
I also concur with the other observations made by commenter IronSlug:
You should be using binding for all of the displayed data, not just the templated items in your GridView control (i.e. tblk1, tblk2, and tblk3, and any other controls similarly set explicitly in code-behind).
Setting anything to null just before you assign it some different non-null value is pointless.
I have a ListView in a FlipView
<FlipView
x:Name="flipView"
AutomationProperties.AutomationId="ItemsFlipView"
AutomationProperties.Name="Item Details"
TabIndex="1"
Width="Auto"
Grid.Row="2"
Grid.Column="1"
VerticalAlignment="Top"
HorizontalAlignment="Center"
ItemsSource="{Binding Source={StaticResource itemsViewSource}}" Padding="0" VirtualizingStackPanel.VirtualizationMode="Standard">
<FlipView.ItemTemplate>
<DataTemplate>
<!--
UserControl chosen as the templated item because it supports visual state management
Loaded/unloaded events explicitly subscribe to view state updates from the page
-->
<UserControl Loaded="StartLayoutUpdates" Unloaded="StopLayoutUpdates">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="1" Orientation="Vertical" Margin="0,100,0,0">
<ListView x:Name="ListofOptions" Height="400" Width="280"
ItemsSource="{Binding QuestionOptions}" SelectedValue="{Binding Answer,Mode=TwoWay}"
IsEnabled="{Binding IsEnabled,Mode=TwoWay}" >
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" >
<StackPanel.Resources>
<common:AltBackgroundConverter x:Key="BGConvertor" />
</StackPanel.Resources>
<StackPanel.Background>
<SolidColorBrush Color="{Binding IndexWithinParentCollection, Mode=OneWay, Converter={StaticResource BGConvertor}}"></SolidColorBrush>
</StackPanel.Background>
<TextBlock Text="{Binding OptionValue}" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackPanel>
</Grid>
</UserControl>
</DataTemplate>
</FlipView.ItemTemplate>
</FlipView>
I write a value conventor of ListView for changing background of alternative row. here is Conventor's code
public class AltBackgroundConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
if (!(value is int)) return null;
int index = (int)value;
if (index % 2 == 0)
return Colors.White;
else
return Colors.LightGray;
}
// No need to implement converting back on a one-way binding
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
when the listbox is out of FlipView everything is Ok but the Conventor doesn't execute when the ListView is in a FlipView. please advice me.
Created a new Split XAML project in VS2012 and added your converter there and used it in ListView and it was still working after moving the ListView inside a FlipView.
I'm now guessing it's a binding issue, happening because root binding object has changed and one of the bindings not resolved as we expect. have you tried moving the Resources tag to upper level which is the FlipeView?
P.S. This is more of a comment, but I don't have reputation for comments!
I am developing Windows8 store app.I have Grid which is populating dynamically
<Grid Grid.Column="1" Margin="0,16,0,0" HorizontalAlignment="Left" VerticalAlignment="Center">
<GridView x:Name="chapterlist" HorizontalAlignment="Left" VerticalAlignment="Top" Width="auto" ItemClick="onChapterClick" Padding="0" Height="600" Margin="0" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<GridView.ItemTemplate>
<DataTemplate>
<StackPanel Width="260" Height="80" Background="{Binding RelativeSource={RelativeSource Self}, Path=alreadyDownload, Converter={StaticResource ColorConverter}}">
<TextBlock x:Name ="AAA" Text="{Binding Path=Chapter}" FontSize="10" Foreground="White" d:LayoutOverrides="Width" Margin="5" TextWrapping="Wrap" />
<TextBlock Text="{Binding Path=Name}" Foreground="White" d:LayoutOverrides="Width" TextWrapping="Wrap"/>
<TextBlock Text="{Binding Path=alreadyDownload}" Foreground="#073363" VerticalAlignment="Bottom" HorizontalAlignment="Right" Margin="0,18,2,2" FontSize="10" d:LayoutOverrides="Width" TextWrapping="Wrap"/>
</StackPanel>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
</Grid>
So i have to change the background color of StackPanel according to TextBlock value like
<TextBlock Text="{Binding Path=alreadyDownload}" Foreground="#073363" VerticalAlignment="Bottom" HorizontalAlignment="Right" Margin="0,18,2,2" FontSize="10" d:LayoutOverrides="Width" TextWrapping="Wrap"/>
I have used ColorConverter like
class ColorConverter : IValueConverter
{
public object Convert(object value, System.Type targetType, object parameter, String culture)
{
if (value != null)
{
if (value.Equals("Already Downloaded "))
return Colors.Red;
else
return Colors.White;
}
return Colors.White;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
But my grid is not reflecting background color(infact no color at all,its transparent).Why it is happening? How can I solve this problem? Please help.I am attaching image for reference. Thanks in advance
So what I want is to show Grid with text Already Downloaded should be having some other color and rest of the Grids with different color.
There are two ways to do the above mentioned scenerio
1)We can add Background property to the objects that populates ObservableCollection and using binding in xaml
<Grid Width="200" Background="{Binding Background}" />
This way we can choose every item color in the grid and change it dynamically just changing object property. Here Background property must be a string assigned with a valid color like
object.Background = "White"
2)Using Converter(as I used) to convert some existing property in your object to a color(refer my Converter class). We can also bind using some property like I used here
<TextBlock Text="{Binding Path=alreadyDownload}"
which'll look like
<StackPanel Width="260" Height="80" Background="{Binding RelativeSource={RelativeSource Self}, Path=alreadyDownload, Converter={StaticResource ColorConverter}}">
<TextBlock x:Name ="AAA" Text="{Binding Path=Chapter}" FontSize="10" Foreground="White" d:LayoutOverrides="Width" Margin="5" TextWrapping="Wrap" />
<TextBlock Text="{Binding Path=Name}" Foreground="White" d:LayoutOverrides="Width" TextWrapping="Wrap"/>
<TextBlock Text="{Binding Path=alreadyDownload}" Foreground="#073363" VerticalAlignment="Bottom" HorizontalAlignment="Right" Margin="0,18,2,2" FontSize="10" d:LayoutOverrides="Width" TextWrapping="Wrap"/>
</StackPanel>
So why my code is not running? Its because the IValueConverter returns object which should be a string, so instead of using
if (value.Equals("Already Downloaded "))
return Colors.Red;
else
return Colors.White;
use
if (value.Equals("Already Downloaded "))
return "#FF0000";
else
return "#FFFFFF";
So its running perfectly
if (value.Equals("Already Downloaded "))
Is it maybe the space between Downloaded and " ?
Use this code instead:
if (value.Equals("Already Downloaded "))
return Brushes.Red;
else
return Brushes.White;
Or If you want to use colors class you can use in this way.
new SolidColorBrush(Colors.Red)
Hope this may be solve your issue.
I've created a listbox, to which i can add and delete items dynamically UI changes accordingly and it works fine.
<ListBox Name="MsgsList" ItemsSource="{Binding Items}" Style="{StaticResource MsgsBoxStyle}">
<ListBox.ItemTemplate>
<DataTemplate x:Name="MsgsDataTemplate">
<StackPanel Tag="{Binding MsgTagInfo}" ManipulationCompleted="StackPanel_Msgs_ManipulationCompleted">
<toolkit:GestureService.GestureListener>
<toolkit:GestureListener Hold="GestureListener_Hold" Tap="GestureListener_Tap"/>
</toolkit:GestureService.GestureListener>
<Grid x:Name="ContentPanelInner" Grid.Row="1" Width="500">
<StackPanel x:Name="stackPanelInner" Width="500">
<Grid VerticalAlignment="Top" Width="500">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding MsgTitle}" Style="{StaticResource MsgLine1}" />
<TextBlock Grid.Column="1" Text="{Binding MsgDate}" Style="{StaticResource MsgDate}" />
</Grid>
<TextBlock Text="{Binding MsgBody}" Style="{StaticResource MsgLine2}" />
</StackPanel>
</Grid>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
but i didn't understand how to change a style for a particular item's textblock, say based on some condition, if i want to change color of specific item's textbox(s), not sure how to access that.
can somebody please help me with this? thanks.
Probably not the easiest way to do this, but arguably the cleanest from a separation of concerns point of view is by using a converter, and binding that to the property you want to monitor...
For example, if your model is changing state based on a boolean property called myProperty, you could use something like this.
<StackPanel Background={Binding myProperty, Converter={StaticResource myBindingConverter}" />
Your converter should return a SolidColorBrush, based on the value of your property.
public class AlternateRowColour : IValueConverter
{
SolidColorBrush normal = new SolidColorBrush(Colors.Transparent);
SolidColorBrush highlighted = new SolidColorBrush(Color.FromArgb(255, 241, 241, 241));
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var myValue = (bool)value
return myValue ? highlighted : normal ;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
I If you just want to change on aspect of an items style, for example its color, you could expose that as property of the model object you are binding. For example, add a property TextColor and bind it as follows:
<TextBlock Text="{Binding MsgBody}" Style="{StaticResource MsgLine2}">
<TextBlock.Color>
<SolidColorBrush Color="{Binding TextColor}"/>
</TextBlock.Color>
</TextBlock>
This will take precedence over the colour defined via the style.
I'm trying to figure out how to build a recursive binding in xaml. I know about HierarchialDataTemplate, but that's not what I want, because my data source is not a collection of items. Specifically, I'm building an exception browser, and am trying to figure out the best way of expressing the exception's InnerException field (which is of course another exception, hence recursion.)
This exception browser is part of a log viewer I'm building. Here is the XAML for the ListView so far:
<ListView x:Name="LogViewerOutput">
<ListView.ItemTemplate>
<DataTemplate DataType="Ushanka.Log.LogMessageEventArgs">
<Expander Style="{StaticResource ExceptionTreeStyle}" Width="Auto">
<Expander.Header>
<StackPanel Orientation="Horizontal">
<Image Stretch="Fill" Width="16" Height="16" Margin="5"
Source="{Binding Path=Level, Converter={StaticResource LogLevelIconConverter}}" />
<TextBlock Text="{Binding Message}" />
</StackPanel>
</Expander.Header>
<Expander.Content>
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Exception.Message}" />
<TextBlock Text="{Binding Exception.Source" />
<!-- Here I would like to somehow be able to recursively browse through the tree of InnerException -->
</StackPanel>
</Expander.Content>
</Expander>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Any ideas? Is this even possible?
I would make a DataTemplate for an Exception and bind the InnerException to a ContentPresenter within it. The ContentPresenter will stop the chain when InnerExpception is null and you can format the exceptions however you want. Something like this:
<DataTemplate DataType="{x:Type Exception}">
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Message}" />
<TextBlock Text="{Binding Source" />
<ContentPresenter Content="{Binding InnerException}" />
</StackPanel>
</DataTemplate>
code to support getting the Exception type for the header:
class TypeConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return value.GetType().ToString();
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
xaml:
<Window.Resources>
<local:TypeConverter x:Key="TypeConverter"/>
<DataTemplate DataType="{x:Type sys:Exception}">
<Expander Header="{Binding Converter={StaticResource TypeConverter}}">
<Expander.Content>
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Message}" />
<TextBlock Text="{Binding Source}" />
<ContentPresenter Content="{Binding InnerException}" />
</StackPanel>
</Expander.Content>
</Expander>
</DataTemplate>
</Window.Resources>