ToggleButton not unchecking when clicked - wpf

I have a ToggleButton that is malfunctioning. As I understand it, a ToggleButton should go checked when clicked then unchecked when clicked again.
The ToggleButton in this example does not. Clicking it just sets it to checked again. Any Ideas why?
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<ToggleButton Width="100" Height="35" Name="btnAddLinkComment" >
<CheckBox Content=" Comment" FlowDirection="RightToLeft" IsHitTestVisible="False"
Focusable="False" IsChecked="{Binding ElementName=txtLinkComment, Path=Text}"
Name="chkHasComment" Margin="5"/>
</ToggleButton>
<Popup IsOpen="{Binding ElementName=btnAddLinkComment,Path=IsChecked}"
PlacementTarget="{Binding ElementName=btnAddLinkComment}" Name="popAddCommentLink"
AllowsTransparency="True" StaysOpen="False" PopupAnimation="Fade" HorizontalOffset="-50"
VerticalOffset="50">
<Border BorderBrush="#FF000000" Background="LightBlue" BorderThickness="1,1,1,1"
CornerRadius="8,8,8,8" Padding="5">
<Grid Background="LightBlue">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80"></ColumnDefinition>
<ColumnDefinition Width="200"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock TextWrapping="Wrap" Foreground="Black">Enter Link Comment:</TextBlock>
<TextBox Grid.Column="1" Name="txtLinkComment" Width="200"></TextBox>
</Grid>
</Border>
</Popup>
</Grid>
</Page>

I guess this happens due to popup being bent to the btnAddLinkComment.isChecked property. I believe what happens is that you're clicking on the button when pop is shown which makes it to close and sets button's IsChecked field to false which puts the button into untoggled state; then the click gets processed by the button itself and since it not toggled it becomes toggled and popup gets shown again. I guess you could resolve the issue by removing the binding and do some handling in code; smth like this:
btnAddLinkComment.Click += btnAddLinkComment_Click;
popAddCommentLink.Closed += popAddCommentLink_Closed;
private void btnAddLinkComment_Click(object sender, RoutedEventArgs e)
{
if (popAddCommentLink.IsOpen && btnAddLinkComment.IsChecked == false)
popAddCommentLink.IsOpen = false;
else if (!popAddCommentLink.IsOpen && btnAddLinkComment.IsChecked == true)
popAddCommentLink.IsOpen = true;
}
private void popAddCommentLink_Closed(object sender, EventArgs e)
{
btnAddLinkComment.IsChecked = false;
}
hope this helps, regards

I am not entirely sure what you want to accomplish but the code below might be a step in the right direction. Please elaborate!
<Window x:Class="ToggleButtonSpike.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300"
xmlns:local="clr-namespace:ToggleButtonSpike">
<Window.Resources>
<local:TextToBool x:Key="StringToBool"/>
</Window.Resources>
<StackPanel>
<ToggleButton Name="Toggle" >
<CheckBox IsHitTestVisible="False"
Content="{Binding ElementName=Comment, Path=Text,
UpdateSourceTrigger=PropertyChanged}"
IsChecked="{Binding ElementName=Comment, Path=Text,
Converter={StaticResource StringToBool}}"/>
</ToggleButton>
<Popup IsOpen="{Binding ElementName=Toggle, Path=IsChecked}"
PlacementTarget="{Binding ElementName=Toggle}">
<StackPanel>
<TextBlock Foreground="White">
Enter comment:
</TextBlock>
<TextBox Name="Comment"/>
</StackPanel>
</Popup>
</StackPanel>
</Window>
using System;
using System.Windows;
using System.Windows.Data;
namespace ToggleButtonSpike
{
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
}
public class TextToBool : IValueConverter
{
#region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return !string.IsNullOrEmpty((string)value);
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
#endregion
}
}

When you click on toggle button. It will checked or unchecked, please kindly remember that. At the first click on it, it will be focused.
Please try:
<ToggleButton Focusable="False"/>
Hope to help you

Related

How to set a button size regarding the height of its container in XAML?

I am developping a WPF application in XAML. I am a beginner and I have an issue with my button. I need to set its height as a proportion of its container which is a grid. I saw that the height can be set to a value or to "Auto", but I don't know how to say to my button that his height must be 3/4 of the height of the grid in which it is contained.
Does anybody know how to deal with that ? Is it possible to do that with XAML ?
The objective is that when the grid grows, the button grows with it.
Any help would be appreciate.
Thanks
Here is the code I wrote :
<Window x:Class="WpfAppButtonSize.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfAppButtonSize"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Grid Height="100" Width="250" HorizontalAlignment="Center" VerticalAlignment="Center">
<Button Content="Button 1" FontSize="30" Height="75" Width="150"/>
</Grid>
</Grid>
For the button, instead of Height="75", I would like to say Height=0.75 * Grid Height
The easiest way is to place the button within its own grid, with rows sized approporiately to generate the spacing.
e.g.
<Grid ...>
<Grid Grid.Row="???" Grid.Column="???" ...>
<Grid.RowDefinitions>
<RowDefinition Height="3*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Button Grid.Row="0" ... />
</Grid>
</Grid>
You can achieve this using converter and binding "ActualHeight" property of Grid.
<Button Height="{Binding ElementName="mygGrid" Path=ActualHeight, Converter={StaticResource percentageConverter}}"/>
If you give your Grid and your Button a name by specifying the x:Name attribute, you could set the Button's Height in the code behind whenever the Grid's size changes.
XAML
<Grid x:Name="MyGrid">
<Button x:Name="MyButton" />
</Grid>
MainWindow.xaml.cs
public MainWindow()
{
InitializeComponent();
MyGrid.PropertyChanged += (s,e) =>
{
if(e.PropertyName == nameof(MyGrid.Height))
{
MyButton.Height = MyGrid.Height * 0.75;
}
}
}
Edit: It may be necessary to use the Grid's ActualHeight property instead of the Height.
I succeded using the following :
Creating a new class Converters with Convert function
Converters.cs
namespace WpfAppButtonSize
{
public class Converters : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
double.TryParse((parameter as string).Replace(',', '.'), NumberStyles.Any, CultureInfo.InvariantCulture, out double param);
return param * (double)value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return true;
}
}
Bind the actual height of my button to the height of my grid + use the converter as a static resouce and a converter parameter
MainWindow.xaml
<Window.Resources>
<converter:Converters x:Key="converter" />
</Window.Resources>
<Grid>
<Grid x:Name="MyGrid" Height="100" Width="250" HorizontalAlignment="Center" VerticalAlignment="Center">
<Button x:Name="MyButton" Content="Button 1" FontSize="30" Width="150" Height="{Binding ElementName=MyGrid, Path=ActualHeight, Converter={StaticResource converter}, ConverterParameter=0.75}" />
</Grid>
</Grid>
**And dont forget to add the converter namespace to the xaml :**
xmlns:converter="clr-namespace:WpfAppButtonSize"
The following post also helped me : XAML Binding to a converter
Thank you all for your help.

Handling GridItems click

Starting with a Grouped Items Page template, I want to be able to perform tasks on the grid items when they are clicked. Namely, I want to change the background image, and add/remove the underlying object to a list of selected items.
Here's my DataTemplate:
<GridView.ItemTemplate>
<DataTemplate>
<Border BorderBrush="LightGray" BorderThickness="2" Margin="0,0,20,20">
<Grid HorizontalAlignment="Left" Width="390" Height="190">
<Grid.Background>
<ImageBrush ImageSource="/Assets/unselected.png" Stretch="None"/>
</Grid.Background>
<StackPanel Orientation="Horizontal" VerticalAlignment="Top">
<Image VerticalAlignment="Top" Stretch="None" Source="{Binding ImageUrl}" Margin="10,10,0,0"/>
<StackPanel MaxWidth="270">
<TextBlock Text="{Binding Summary}"/>
<TextBlock Text="{Binding Brand}" />
<TextBlock Text="{Binding Detail}" TextWrapping="Wrap" />
</StackPanel>
</StackPanel>
</Grid>
</Border>
</DataTemplate>
</GridView.ItemTemplate>
OnTap, I want to togle the ImageSource value of the Grid.Background from unselected.png to selected.png. This I believe I can do using VisualStates and Storyboards, but I've been unable to get this to work in the past (I'll spare you the chaos of my attempts in xaml).
Needless to say, I've tried following the steps detailed here using Blend, but the Grid.Background property doesn't seems to be state specific. If I try changing the background brush in the Pressed or Selected states, it also changes for the Normal state.
Since I want to grab the data context of the selected item and add/remove it from a list, should I just be handling all this together in an OnTap event handler? I would prefer to keep these concerns separated, but I'll do what I need to...
thanks!
One clean way to do this would be engage the selection method (Tap) in such a way that it only opperates on its items, and the items themselves have properties which Implement the INotifyPropertyChanged interface
Your View Model would have a collection of your custom objects that have properties that can notify the ui
public class MyObject : INotifyPropertyChanged
{
private string _summary;
public string summary
{
get {return _summary}
set
{
_summary = value;
OnPropertyChanged()
}
}
//Other Properties: brand || detail
private ImageSource _backgroundImage;
public ImageSource backgroundImage
{
get {return _backgroundImage}
set
{
_backgroundImage = value;
OnPropertyChanged()
}
}
private bool _IsSelected;
public bool IsSelected
{
get {return _IsSelected;}
set
{
_IsSelected = value;
OnPropertyChanged()
}
}
}
Then although your code behind can be used to change the value of IsSelected, or Background image ... if you choose to go with IsSelected, you can still separate your concerns by not directly setting the resource of the background image in code behind. The Codebehind will only iterate over the items to toggle the IsSelected property, and you can use xaml to define the image that the background should use by creating a custom converter.
public class MyCustomControlOrPage.cs : UserControl //Or ApplicationPage
{
//.......code
protected void HandleTap(object sender, GestureEventArgs e)
{
foreach(var item in ((Listbox)sender).ItemsSource)
{
((MyObject)item.IsSelected = (MyObject)item.Name == (e.NewItems[0] as MyObject).Name? true: false;
}
}
}
then the converter
public class BackgroundConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
ImageSource source = value == true ? new BitmapImage(uriForSelected) : new BitmapImage(uriForunselected);
return source;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
BitmapImage thisValue = value as BitmapImage;
return thisValue;
}
}
and FINALLY the XAML where the grid background binds to the IsSelected property and allows the converter to transform the bool to an ImageSource of type BitmapImage:
//add xmlns:Converters=clr-namesapce:Yournamespace.UpTo.TheNamespaceBackgroundConverterIsIn" to the page or control definition
<UserControl.Resources>
<Converters:BackgroundConverter x:key="BgSourceConverter" />
</UserControl.Resources>
<GridView.ItemTemplate>
<DataTemplate>
<Border BorderBrush="LightGray" BorderThickness="2" Margin="0,0,20,20">
<Grid HorizontalAlignment="Left" Width="390" Height="190">
<Grid.Background>
<ImageBrush ImageSource="{Binding Path=IsSelected, Mode=TwoWay, Converter={Binding Source={StaticResource BGSourceConverter}}}" Stretch="None"/>
</Grid.Background>
<StackPanel Orientation="Horizontal" VerticalAlignment="Top">
<Image VerticalAlignment="Top" Stretch="None" Source="{Binding ImageUrl}" Margin="10,10,0,0"/>
<StackPanel MaxWidth="270">
<TextBlock Text="{Binding Summary}"/>
<TextBlock Text="{Binding Brand}" />
<TextBlock Text="{Binding Detail}" TextWrapping="Wrap" />
</StackPanel>
</StackPanel>
</Grid>
</Border>
</DataTemplate>
</GridView.ItemTemplate>

XAML collapse all child elements

I am working on a WPF Xaml application. The app has various stackpanels (that behave like icons) that I need to change the Visibility based on certain criteria.
Question:
How can I collapse all child elements (stackpanels)?
I am collapsing each one by one in the backend in vb.net. But much rather find a cool way to do it all at once.
In that case you can have two options
you can achieve it through style(This will not work if your following MVVM, that is if your binding)
Create coustom control
With Style:
Write the style as below with the target type which is used to display the image
<Window.Resources>
<Style TargetType="TextBox">
<Setter Property="Visibility" Value="Collapsed"/>
</Style>
</Window.Resources>
<Grid>
<StackPanel>
<TextBox Height="26" Width="200" Name="text1"/>
<TextBox Height="26" Width="200" Name="text2"/>
<Button Height="26" Width="200" Click="Button_Click_2" />
</StackPanel>
</Grid>
TextBox by default will be collapsed you can make it visible based on the search in the backend code
Custom control:
This will be just a wrapper for what ever control your using to display the icon but with only one change is that the default visibility will be collapsed. Then you can make it visible which ever you want
Override hide the already existing Visibility the property with the default value collapsed
You can set the visibility to parent instead of setting it to each control
For example
<StackPanel>
<StackPanel Name="pane1">
<Button Height="30" Width="200" Content="one" Click="Button_Click" />
</StackPanel>
<StackPanel Name="panel2">
<Button Height="30" Width="200" Content="two" Click="Button_Click_1" />
</StackPanel>
</StackPanel>
In you back end write the logic to set the visibility for stackpanel instead of each control
private void Button_Click(object sender, RoutedEventArgs e)
{
pane1.Visibility = Visibility.Collapsed;
panel2.Visibility = Visibility.Visible;
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
panel2.Visibility = Visibility.Collapsed;
pane1.Visibility = Visibility.Visible;
}
If your following mvvm then bind to the visibility property of the stack panel like below
<StackPanel>
<StackPanel Visibility="{Binding CanShowPanel1}">
<Button Height="30" Width="200" Content="one" Click="Button_Click" />
</StackPanel>
<StackPanel Visibility="{Binding CanShowPanel2}">
<Button Height="30" Width="200" Content="two" Click="Button_Click_1" />
</StackPanel>
</StackPanel>
Bind them using an IValueConverter implementation like BooleanToVisibilityConverter.
If that isn't good enough, you will have to do them one by one. Maybe write a custom behavior?
The easiest way to do that is to use IValueConverter with parameter.
<StackPanel>
<StackPanel Visibility="{Binding TheQuery,Converter={StaticResource QueryConverter,ConverterParameter="MyFirstStackPanelVisible"}}">
</StackPanel>
<StackPanel Visibility="{Binding TheQuery,Converter={StaticResource QueryConverter,ConverterParameter="MySecondStackPanelVisible"}}">
</StackPanel>
</StackPanel>
public class QueryConverter: IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
switch((string)parameter)
{
case "MyFirstStackPanelVisible"
bool result =CheckQueryCriteriaForFirstStackPanel();
return Visibility.Visible or Visibility.Collapsed;
case "MySecondStackPanelVisible"
bool result =CheckQueryCriteriaForSecondStackPanel();
return Visibility.Visible or Visibility.Collapsed;
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Of course you shouldn't make CheckQueryCriteriaFor... function for every case.
This approach guarantee logic to be in one place.

Closing a Popup when its parent gets collapsed

I've been struggling with this for quite some time and I can't seem to find a proper solution. This is the scenario stripped down. Imagine you have the following XAML:
<Grid x:Name="LayoutRoot" Background="White">
<Grid x:Name="Host" Width="200" Height="200">
<Popup IsOpen="True">
<Button Content="Some Button" Click="Button_Click" />
</Popup>
</Grid>
</Grid>
In the Button_Click event handler all I do is collapse the grid with name Host.
private void Button_Click(object sender, RoutedEventArgs e)
{
this.Host.Visibility = System.Windows.Visibility.Collapsed;
}
What I expected was that the Popup would close therefore hiding the Button. I understand that Popups are not in the same VisualTree and I understand why this might not be working the way I expect it to, but there should be some kind of mechanism for this to happen automatically. The only workaround that comes to my mind is on LayoutUpdated to traverse the visual tree up and ask each Button's parent if it is visible and if I meet a collapsed parent -> close the Popup. However, imagine the performance hit having a HUGE visual tree. It's insane to traverse the visual tree on every layout pass.
I'm open to any sort of suggestions.
EDIT: It seems that I did not explain fully my scenario. The case is to collapse the Popup if ANY of its parent gets collapsed (not just the immediate one). In WPF there is a useful property called IsVisible which is different than Visibility. For example, Visibility might still be Visible, but IsVisible will be false in this scenario.
Best Regards,
K
I think you found a bug, or at least a "weirdness" in the popup control - check this out:
My initial thought was to simply Bind the Visibility of the Popup to the Host. This SHOULD work.
<Grid x:Name="LayoutRoot" Background="White">
<Grid x:Name="Host" Width="200" Height="200" Background="Aqua">
<Popup IsOpen="True" Visibility="{Binding ElementName=Host, Path=Visibility}" Height="100" Width="100">
<Button Content="Some Button" Click="Button_Click"/>
</Popup>
</Grid>
</Grid>
But it does not work. The "Host" grid disappears, but I still see the button. This confused me, so I fired up Silverlight Spy, and check this out - setting the Visibility of the Popup does NOT hide the button!
See Demo Video
Anyway, in order to make this work, you just need to massage things a little bit in order tie the Host Visibility to the IsOpen property. I used a converter here:
<UserControl.Resources>
<Junk:VisibilityToBoolConverter x:Key="VisibilityToBoolConverter"/>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White">
<Grid x:Name="Host" Width="200" Height="200" Background="Aqua">
<Popup IsOpen="{Binding ElementName=Host, Path=Visibility, Converter={StaticResource VisibilityToBoolConverter}}" Height="100" Width="100">
<Button Content="Some Button" Click="Button_Click"/>
</Popup>
</Grid>
</Grid>
private void Button_Click(object sender, RoutedEventArgs e)
{
this.Host.Visibility = System.Windows.Visibility.Collapsed;
}
public class VisibilityToBoolConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return ((Visibility) value) == Visibility.Visible;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
That's working for me.
If you just want to close the popup, why don't you set the IsOpen at the popup to false.
<Grid x:Name="LayoutRoot" Background="White">
<Grid x:Name="Host" Width="200" Height="200">
<Popup x:Name="HostPopup" IsOpen="True">
<Button Content="Some Button" Click="Button_Click" />
</Popup>
</Grid>
</Grid>
private void Button_Click(object sender, RoutedEventArgs e)
{
this.HostPopup.IsOpen = false;
}
This closes the popup.

In WPF how to change a DataTemplate's Textblock's text binding in code?

I have a ListBox whose ItemsSource is bound to a list of objects. The Listbox has a ItemTemplate with a DataTemplate containing a TextBlock. The textblock's Text is bound to the object's Name property (i.e. Text="{Binding Name}").
I would like to provide a radio button to show different views of the same list. For example allow a user to toggle between the Name property and an ID property.
I found a SO answer for this at 2381740 but I also have border and a textbox style set in data template (see code below).
Is there anyway to just reset the Textblock binding? I don't want to have to recreate the entire datatemplate. Actually I'm not even sure how to do that, is there an easy way to translating xaml to code?.
Thanks
Cody
<DataTemplate>
<Border Margin="0 0 2 2"
BorderBrush="Black"
BorderThickness="3"
CornerRadius="4"
Padding="3">
<TextBlock Style="{StaticResource listBoxItemStyle}"
Text="{Binding Name}" />
</Border>
</DataTemplate>
Wallstreet Programmer's solution works well for you because you are using radio buttons. However there is a more general solution that I thought I should mention for future readers of this question.
You can change your DataTemplate to use plain "{Binding}"
<DataTemplate x:Key="ItemDisplayTemplate">
<Border ...>
<TextBlock ...
Text="{Binding}" />
</Border>
</DataTemplate>
Then in code you don't have to recreate a full DataTemplate. All you have to do is recreate this:
<DataTemplate>
<ContentPresenter Content="{Binding Name}" ContentTemplate="{StaticResource ItemDisplayTemplate}" />
</DataTemplate>
which is easy:
private DataTemplate GeneratePropertyBoundTemplate(string property, string templateKey)
{
var template = FindResource(templateKey);
FrameworkElementFactory factory = new FrameworkElementFactory(typeof(ContentPresenter));
factory.SetValue(ContentPresenter.ContentTemplateProperty, template);
factory.SetBinding(ContentPresenter.ContentProperty, new Binding(property));
return new DataTemplate { VisualTree = factory };
}
This is particularly convenient if you have many properties, even in your radio button example.
Just make it simple for yourself and use two textblocks and hide one of them.
XAML:
<Window x:Class="Test.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="300" Width="300">
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</Window.Resources>
<StackPanel>
<RadioButton Name="nameRadioBtn" Content="Name" IsChecked="True"/>
<RadioButton Name="lengthRadioBtn" Content="Length" />
<ListBox
ItemsSource="{Binding Path=Items}">
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Red" BorderThickness="1">
<Grid>
<TextBlock
Text="{Binding .}"
Visibility="{Binding Path=IsChecked, ElementName=nameRadioBtn,
Converter={StaticResource BooleanToVisibilityConverter}}" />
<TextBlock
Text="{Binding Path=Length}"
Visibility="{Binding Path=IsChecked, ElementName=lengthRadioBtn,
Converter={StaticResource BooleanToVisibilityConverter}}" />
</Grid>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</Window>
Code behind:
using System.Collections.Generic;
using System.Windows;
namespace Test
{
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
DataContext = this;
}
public IEnumerable<string> Items
{
get
{
return new List<string>() {"Bob", "Sally", "Anna"};
}
}
}
}
You can also use a value converter to pick any property of your data object. You will need to bind to the whole object instead of individual properties. If your data object implements INotifyPropertyChanged then this solution will not work for you.
XAML
<Window x:Class="Test.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Test="clr-namespace:Test"
Height="300" Width="300">
<Window.Resources>
<Test:PropertyPickerConverter x:Key="PropertyPickerConverter" />
</Window.Resources>
<StackPanel>
<RadioButton Content="Name" Click="OnRadioButtonClick" IsChecked="True"/>
<RadioButton Content="Length" Click="OnRadioButtonClick" />
<ListBox
ItemsSource="{Binding Path=Items}"
Name="_listBox">
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Red" BorderThickness="1">
<StackPanel>
<TextBlock
Text="{Binding ., Converter={StaticResource PropertyPickerConverter}}" />
</StackPanel>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</Window>
code behind:
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
namespace Test
{
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
_propertyPickerConverter = FindResource("PropertyPickerConverter") as PropertyPickerConverter;
_propertyPickerConverter.PropertyName = "Name";
DataContext = this;
}
public IEnumerable<string> Items
{
get
{
return new List<string>() {"Bob", "Sally", "Anna"};
}
}
private void OnRadioButtonClick(object sender, RoutedEventArgs e)
{
_propertyPickerConverter.PropertyName = (sender as RadioButton).Content as string;
_listBox.Items.Refresh();
}
private PropertyPickerConverter _propertyPickerConverter;
}
public class PropertyPickerConverter : IValueConverter
{
public string PropertyName { get; set; }
#region IValueConverter Members
public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
string item = value as string;
switch (PropertyName)
{
case "Name": return item;
case "Length": return item.Length;
default: return null;
}
}
public object ConvertBack(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new System.NotImplementedException();
}
#endregion
}
}

Resources