I have a custom ItemTemplate for a ListBox and I need to "bind" a TextBlock to some special method / property.
My ListBox Source is an ObservableCollection<SearchResultItem>. SearchResultItem containing some properties.
The text need to change based on the value of another object. E.G if this object equals "foo" I need the text value to call the method GetProperty("foo") on the SearchResultItem to get the correct value.
Here is a sample of code:
<DataTemplate>
..
//Here is a Label bound to the Date Property of the SearchResultItem
<Label Margin="2,2,2,0" Grid.Row="0" Grid.Column="2" Content="{Binding Path=Date}" HorizontalAlignment="Right" HorizontalContentAlignment="Right" />
//Here is the textblock that needs to call the method with the parameter based on the value of the other object.
<TextBlock Margin="2,2,2,0" TextTrimming="CharacterEllipsis" Grid.Row="0" Grid.Column="1" Text="I need some help there" HorizontalAlignment="Left" VerticalAlignment="Center" Foreground="Black"/>
..
</DataTemplate>
Do you have any idea on how to do that or a better way to do it?
Edit:
-Let's assume SearchResultItem comes from an external library and only exposes the GetProperty method.
-Let's say the "foo" value comes from ConfigurationManager.AppSettings["propertyName"]; if it helps.
OK, because your properties never change, here's one solution. You can do this via another property on your SearchResultItem class:
public string MyTextBinding
{
get
{
return myDictionary.ContainsKey("foo") ? return myDictionary["foo"] : return "myDictionary doesn't contain foo";
}
}
Then just bind your textbox to this property:
<DataTemplate>
<Label Margin="2,2,2,0" Grid.Row="0" Grid.Column="2" Content="{Binding Path=Date}" HorizontalAlignment="Right" HorizontalContentAlignment="Right" />
<TextBlock Margin="2,2,2,0" TextTrimming="CharacterEllipsis" Grid.Row="0" Grid.Column="1" Text="{Binding Path=MyTextBinding, Mode=OneWay}" HorizontalAlignment="Left" VerticalAlignment="Center" Foreground="Black"/>
</DataTemplate>
Just use a IValueConverter that takes a SearchResultItem and return the expected text
<TextBlock Margin="2,2,2,0" TextTrimming="CharacterEllipsis"
Grid.Row="0" Grid.Column="1"
Text="{Binding Path=.,
Converter={StaticResource PropertyValueFromSearchResultItemConverter},
ConverterParameter=Foo}"
HorizontalAlignment="Left" VerticalAlignment="Center" Foreground="Black"/>
Related
I am using MVVM, I am trying to bind three TextBox's to a Client class properties as follow:
<TextBox Text="{Binding NewClient.Name, Mode=OneWayToSource}" Grid.Column="1" HorizontalAlignment="Left" Margin="5"/>
<TextBox Text="{Binding NewClient.NameInLatin, Mode=OneWayToSource}" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Left" Margin="5"/>
<StackPanel Orientation="Horizontal" Grid.Row="2" Grid.Column="1" >
<TextBox Text="{Binding NewClient.IDNumber, Mode=OneWayToSource}" Margin="5" />
<Button Content="{Binding ScanLabel,Source={StaticResource LocalStrings}}" Margin="4"/>
</StackPanel>
In my View Model I defined the NewClient property the classic way:
private Client newClient;
public Client NewClient
{
get { return newClient; }
set
{
newClient = value;
NotifyPropertyChanged("NewClient");
}
}
When place a breakpoint inside a boolean property just to test the value of newClient, and I find it null.
So why is it the newClient property loses it's value?
Here is the entire xaml part:
<Border Background="AntiqueWhite"
DataContext="{StaticResource ServicesViewModel}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="120" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding NameLabel, Source={StaticResource LocalStrings}}"
Style="{StaticResource SubTitles}" />
<TextBlock Text="{Binding NameInLatinLabel, Source={StaticResource LocalStrings}}"
Grid.Row="1"
Style="{StaticResource SubTitles}" />
<TextBlock Text="{Binding IDNumberLabel, Source={StaticResource LocalStrings}}"
Grid.Row="2"
Style="{StaticResource SubTitles}" />
<TextBox Text="{Binding NewClient.Name, Mode=OneWayToSource}"
Grid.Column="1"
HorizontalAlignment="Left" />
<TextBox Text="{Binding NewClient.NameInLatin, Mode=OneWayToSource}"
Grid.Row="1"
Grid.Column="1"
HorizontalAlignment="Left" />
<StackPanel Orientation="Horizontal"
Grid.Row="2"
Grid.Column="1">
<TextBox Text="{Binding NewClient.IDNumber, Mode=OneWayToSource}" />
<Button Content="{Binding ScanLabel,Source={StaticResource LocalStrings}}" />
</StackPanel>
</Grid>
</Border>
I tired to bind to a property I created called Name, and the binding did work.
By default TextBox.Text updates when a control loses focus, so if you need to update your property every time text changes you should use binding like this:
{Binding NewClient.Name, UpdateSourceTrigger=PropertyChanged}
How to: Control When the TextBox Text Updates the Source
If it still doesn't work, then probably NewClient is not initalized. In Debug Output window should show you issues with bindings.
You don't need to use the name of the item held in the datacontext. Simply report its property only:
Before:
Binding NewClient.Name, Mode=OneWayToSource
after
Binding Name, Mode=OneWayToSource
Also OneWayToSource is primarily used for read-only data. Remove that to
Binding Name
I was experiencing similar problem. In ViewModel I did binding to a Class property.
class SampleClass
{
public string Name {get; set;}
public int Age {get; set;}
}
class ViewModelClass
{
public SampleClass Sample {get; set;}
}
And I found thhat for binding to work, should be used Properties in SampleClass, not Fields. It helped me.
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.
Is it possible to use a converter/style selector without having to use databinding?
I want the style of my object to change if a certain value is reached.
Here is what i have
<Border Name="watch0_0Border" Grid.Row="0" Grid.Column="0" Style="{StaticResource clockBorderStyle}">
<StackPanel Style="{StaticResource clockStackPanelStyle}">
<TextBlock Name="watch0_0Time" Style="{StaticResource clockTimerStyle}">07:45:23</TextBlock>
<TextBlock Name="watch0_0Description" Style="{StaticResource clockTextStyle}" Text="{Binding ElementName=watch0_0WorkDescription, Path=Text}"></TextBlock>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<Button Name="watch0_0Pause" Margin="5" Click="watch0_0Pause_Click">Pause</Button>
<Button Name="watch0_0SetNewTime" Margin="5" Click="watch0_0SetNewTime_Click">Set new time</Button>
</StackPanel>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<TextBox Name="watch0_0Hours" Margin="5">0</TextBox>
<TextBox Name="watch0_0Minutes" Margin="5">0</TextBox>
<TextBox Name="watch0_0Seconds" Margin="5">0</TextBox>
</StackPanel>
<TextBox Name="watch0_0WorkDescription" TextAlignment="Center" Margin="5">Work description</TextBox>
</StackPanel>
</Border>
I want to canhe the background of the border when the times goes under 0.
If your timer has access to main window (which can access watch0_0Border) or watch0_0Border direct (by passing these in when timer was created) then you should just be able to use the UI dispatcher to set watch0_0Border.BorderBrush (or whatever property) when timer hits zero.
I have a TextBlock with a tooltip that displays the same data, in case of truncation. However if the property that TextBlock.Text and the tooltip's text are bound to is empty (null or zero length string) the tooltip appears as a small empty box. Is there a way to hide this and show no tooltip in this case?
<TextBlock Text="{Binding Text}">
<util:ToolTipManager.ToolTip>
<TextBlock TextWrapping="Wrap" Text="{Binding Text}" />
</util:ToolTipManager.ToolTip>
</TextBlock>
I have tried using a StringToVisibilityConverter by adding Visibility="{Binding Text, Converter={StaticResource StringToVisConverter}}" to the TextBlock without any luck.
I also tried implementing the answer given Hide tooltip if binding is null but that seems specific to their set-up (or at least I haven't figured out how to adapt it successfully).
(ToolTipManager is from http://www.codeproject.com/Articles/36078/Silverlight-2-0-How-to-use-a-DataBinding-with-the, used to provide the data binding for the tooltip.)
Edit:
In response to the comments, here is the XAML I tried for the related question mentioned above:
<TextBlock Text="{Binding PointName}">
<local:ToolTipManager.ToolTip>
<Grid>
<TextBlock TextWrapping="Wrap" Text="{Binding PointName}"/>
<Rectangle Fill="Transparent" Visibility="{Binding PointName, Converter={StaticResource StringToVisConverter}}" />
</Grid>
</local:ToolTipManager.ToolTip>
</TextBlock>
And here is my String to Visibility converter code:
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
string visible = (string)value;
return (!String.IsNullOrWhiteSpace(visible) ? Visibility.Visible : Visibility.Collapsed);
}
I assume you are using Siverlight 4 as it is one of your tags.
In Silverlight 4, I am pretty sure that you don't need the ToolTipManager anymore.
You can just wrap the Rectangle and the TextBlock with a Grid, like this,
<Grid>
<TextBlock Text="{Binding PointName}"/>
<Rectangle Fill="Transparent" Visibility="{Binding PointName, Converter={StaticResource BooleanToVisibilityConverter}}" ToolTipService.ToolTip="{Binding PointName}"/>
</Grid>
UPDATE:
<Grid>
<TextBlock Text="{Binding PointName}"/>
<Rectangle Fill="Transparent" Visibility="{Binding PointName, Converter={StaticResource BooleanToVisibilityConverter}}">
<ToolTipService.ToolTip>
<TextBlock TextWrapping="Wrap" Text="{Binding PointName}"/>
</ToolTipService.ToolTip>
</Rectangle>
</Grid>
If you are using Silverlight 5, the following seems to work:
<ToolTipService.ToolTip>
<ToolTip Visibility="{Binding WhatDeterminesTooltipVisibility}">
<Border Background="Azure" Width="100" />
</ToolTip>
</ToolTipService.ToolTip>
I have a textblock which is inside a listbox and I am trying to write an if statement which is dependant on the contents of this textblock. I am trying to get the data from the TextBlack which I have named "category1" however when I try to write my if statement I am getting a message which just says
"the name category1 does not exist in the current context"
I tired moving that TextBLock out of the ListBox and it works fine but wont work while its inside there. Does anyone know how to reference this textblock.
Here is the my XAML code
<ListBox x:Name="HINList" Margin="0,300,-12,0" ItemsSource="{Binding Details}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,17" Width="432">
<TextBlock Text="{Binding HINNumber}" TextWrapping="Wrap" Margin="12,-6,12,0" Style="{StaticResource PhoneTextExtraLargeStyle}"/>
<TextBlock Text="{Binding CategoryLetter}" TextWrapping="Wrap" Margin="12,-6,12,0" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="category1" Text="{Binding Category1}" TextWrapping="Wrap" Margin="12,-6,12,0" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock Text="{Binding Category2}" TextWrapping="Wrap" Margin="12,-6,12,0" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock Text="{Binding Category3}" TextWrapping="Wrap" Margin="12,-6,12,0" Style="{StaticResource PhoneTextNormalStyle}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Assuming you're writing your if statement in the code behind file, wouldn't something like:
if(((WhateverTypeIsInDetailsCollection)HINList.SelectedItem).Category1 == something) {
// then do whatever you want
}
As Russell pointed out there is a category1 item for every entry in the list. I assume you wanted to do something with the selected item.
This is due to xaml namescopes. The names inside a DataTemplate are in a different namescope than outside, that's why you can't access them (what #Russell pointed is part of why it's done this way).
I think that you want to access that field for the "Category1" property on the selected item of the HINList ListBox that is bound to the Details collection. What you can do is set the binding on the Category1 to be two way, and bind the SelectedItem of the ListBox to a Detail item like so:
xaml:
<ListBox x:Name="HINList" ItemsSource="{Binding Details}"
SelectedItem={Binding SelectedDetailItem, Mode=TwoWay}>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,17" Width="432">
<TextBlock Text="{Binding Category1, Mode=TwoWay}" TextWrapping="Wrap" .../>
<!-- the other fields -->
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
code-behind
if(SelectedDetailsItem.Category1==...)
{
....
}
Hope this helps :)