Toggle TextWrapping in TextBox inside FlipView - c#

I have a FlipView where each FlipViewItem contains a TextBox bound to an ObservableCollection and I need to toggle TextWrapping for the TextBox's that are inside the FlipView.
I have tried everything I could think of and no help online thus far. Not a single result I could find.
How can I do this?
XAML:
...
// This part is for the AppBar Toggle button
<ToggleButton x:Name="wordWrapToggleButton" Style="{StaticResource WordWrapAppBarButtonStyle}" />
...
// For the FlipView
<FlipView x:Name="flipView" Grid.Row="1" Margin="0, 50, 0, 0" ItemsSource="{Binding Note, Mode=TwoWay}" Loaded="flipView_Loaded" SelectionChanged="flipView_SelectionChanged" FontSize="12.667">
<FlipView.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding Contents, Mode=TwoWay}" Tag="{Binding Title, Mode=TwoWay}" TextWrapping="{Binding ElementName=wordWrapToggleButton, Path=.CheckState, Mode=TwoWay}" IsSpellCheckEnabled="True" AcceptsReturn="True" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" BorderBrush="{x:Null}" FontSize="{Binding ElementName=flipView, Path=FontSize, Mode=OneWay}" />
</DataTemplate>
</FlipView.ItemTemplate>
</FlipView>

You have to create a binding converter that converts from bool to TextWrapping
public class BooleanToTextWrappingConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
return (value is bool && (bool)value) ? TextWrapping.Wrap : TextWrapping.NoWrap;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
return value is TextWrapping && (TextWrapping)value == TextWrapping.Wrap;
}
}
and use that in your binding
<Page.Resources>
<local:BooleanToTextWrappingConverter x:Key="BooleanToTextWrappingConverter"/>
</Page.Resources>
...
<DataTemplate>
<TextBox Text="{Binding Contents, Mode=TwoWay}"
TextWrapping="{Binding Path=IsChecked, ElementName=wordWrapToggleButton,
Converter={StaticResource BooleanToTextWrappingConverter}}"/>
</DataTemplate>
Note that the TextWrapping binding isn't two-way, as that makes no sense.

Related

How to highlight ListBox Items matching a certain condition

I have 2 ListBoxes defined thus:
<ListBox Name="aggregatesListBox" SelectionChanged="aggregatesList_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Amount}"/>
<TextBlock Text="{Binding Path=AccountId}"/>
<TextBlock Text="{Binding Path=Name}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<ListBox Name="postingsListBox" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=PostingId}" />
<TextBlock Text="{Binding Path=Amount}" />
<TextBlock Text="{Binding Path=CreatedDate}" />
<TextBlock Text="{Binding Path=AccountId}" />
<TextBlock Text="{Binding Path=Name}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I want all items in the postings list to be highlighted (in some way, preferably background colour) if they share the same Account Id as the currently selected aggregated item.
What are my options?
On the advice given I have modified as follows
<ListBox Name="postingsListBox" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<StackPanel.Resources>
<local:IdToBrushConverter x:Key="IdToBrushConverter" />
</StackPanel.Resources>
<StackPanel.Background>
<MultiBinding Converter="{StaticResource IdToBrushConverter}">
<Binding ElementName="aggregatesListBox" Path="SelectedItem.AccountId"/>
<Binding Path="AccountId"/>
</MultiBinding>
</StackPanel.Background>
<TextBlock Text="{Binding Path=PostingId}" />
<TextBlock Text="{Binding Path=Amount}" />
<TextBlock Text="{Binding Path=CreatedDate}"/>
<TextBlock Text="{Binding Path=AccountId}" />
<TextBlock Text="{Binding Path=Name}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
and
public class IdToBrushConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
System.Windows.Media.Color colour;
if (values[0] == DependencyProperty.UnsetValue || values[1] == DependencyProperty.UnsetValue || ((int)values[0] != (int)values[1]))
colour = System.Windows.Media.Colors.White;
else
colour = System.Windows.Media.Colors.CornflowerBlue;
return new SolidColorBrush(colour);
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException("");
}
}
An attribute on the Window is required so that the brush converter can be located
xmlns:local="clr-namespace:MyAccountingThing"
I also changed the behind the scenes logic to use a list of Objects as the ItemsSource of each of the 2 Listboxes rather than the DataRowView I had previously.
Sorted - Thanks!
You could use a multibinding with a converter, here's an example.
XAML
<ListBox x:Name="list1"
ItemsSource="{Binding List1}">
</ListBox>
<ListBox x:Name="list2"
ItemsSource="{Binding List2}"
Grid.Column="2">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding .}">
<TextBlock.Background>
<MultiBinding Converter="{StaticResource converter}">
<Binding Path="SelectedItem" ElementName="list1"/>
<Binding Path="."/>
</MultiBinding>
</TextBlock.Background>
</TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
On my silly example, I used the MultiBiding to be able to pass more than one parameter to the Converter, which is the selectedItem on the list1 and the currentItem that ListBox2 is applying the Template, next, I used the converter to compare the received values:
Converter:
public class Converter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var selectedValueList1 = values[0];
var currentItemList2 = values[1];
if(selectedValueList1 == null) // Listbox 1 has no selected Item
return Brushes.Black;
if (selectedValueList1 == currentItemList2)
return Brushes.Red;
return Brushes.Transparent;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
And of course, you have to elaborate better the test on your converter, in my example I just pass two strings to be compared.
And that is it, it works like expected.

Triggering button visibility based on position in ListView

I have a ListView with multiple items. The ListViewItems is a template that contains details about the item from the ObservableCollection and a Button.
My goal is for the button to only be visible on the very last ListViewItem. To that end I implemented a converter and bound it to the Button's visibility, which checks ListViewItem's index vs the ListView's count and returns Visibility.Visible or Visibility.Collapsed.
This works fine when the page first loads, but when I add additional items to the ListView, it doesn't update the existing ListViewItems, it only runs the Converter for the new Items.
Is there a nice xaml (MVVM friendly) way to trigger it to run the Binding?
My XAML:
<ListView x:Name="lstBox" ItemsSource="{Binding People}" Background="Yellow" >
<ListView.ItemTemplate>
<DataTemplate>
<WrapPanel>
<TextBlock Text="{Binding Firstname}" />
<Button Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type ListView}}, Path=DataContext.AddPersonCommand}" Content="Add Person" Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type ListViewItem}}, Converter={StaticResource IsLastItemToVisibilityConverter}}" />
</WrapPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
My Converter:
public class IsLastItemToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
ListViewItem item = value as ListViewItem;
ListView ListView = ItemsControl.ItemsControlFromItemContainer(item) as ListView;
int index = ListView.ItemContainerGenerator.IndexFromContainer(item);
if (index == ListView.Items.Count - 1)
{
return Visibility.Visible;
}
else
{
return Visibility.Collapsed;
}
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
Another possibility is to pass the item as a command parameter.
<ListView x:Name="lstBox"
Background="Yellow"
ItemsSource="{Binding People}">
<ListView.ItemTemplate>
<DataTemplate>
<WrapPanel>
<TextBlock Text="{Binding FirstName}" />
<Button Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type ListView}},
Path=DataContext.AddPersonCommand}"
CommandParameter="{Binding}"
Content="Add Person"
Visibility="{Binding IsEnabled,
RelativeSource={RelativeSource Self},
Converter={StaticResource BooleanToVisibilityConverter}}" />
</WrapPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
The CanExecute of the command should return true only when the item is last in the collection. Something like this:
private bool CanAddPerson(object arg)
{
return _people.Last().Equals(arg);
}
The ObservableCollection should contain items of a ViewModel Type (like Person or whatever you want to call it). That viewmodel should contain a Visibility value for each of the items button and you change your converter to a BoolToVisibilityConverter.
In this sollution you just have to update the visibility of items when you change the collection. You have an event where you can do this. Check this answer for more details about the collection changed event.
Hope it helps.

Make visibility of listbox items to be visible when clicked on a button

XAML:
<ListBox Height="163" HorizontalAlignment="Left" Margin="0,-24,0,0" Name="listBox2" VerticalAlignment="Top" Width="446" SelectedValuePath="" SelectionChanged="listBox2_SelectionChanged" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock x:Name="LblPassword" HorizontalAlignment="Left" TextWrapping="Wrap" Text="{Binding RegistPassword}" VerticalAlignment="Top" Visibility="Collapsed" Foreground="Black"/>
<TextBlock x:Name="LblSecQn" HorizontalAlignment="Left" TextWrapping="Wrap" Text="{Binding SecurityQn}" VerticalAlignment="Top" Margin="10,50,0,0" Visibility="Visible" Foreground="Black"/>
<TextBlock x:Name="LblSecAns" HorizontalAlignment="Left" TextWrapping="Wrap" Text="{Binding SecurityAns}" VerticalAlignment="Top" Visibility="Collapsed" Foreground="Black"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<TextBlock x:Name="LblEmail" Text="" HorizontalAlignment="Left" Margin="24,59,0,0" TextWrapping="Wrap" Foreground="Black" FontSize="30" VerticalAlignment="Top" Visibility="Collapsed"/>
<Button x:Name="BtnSubmit" Content="Submit" HorizontalAlignment="Left" Margin="116,316,0,0" VerticalAlignment="Top" Height="88" Width="193" Click="BtnSubmit_Click" Foreground="Black" BorderBrush="Black"/>
.CS:
private void BtnSubmit_Click(object sender, RoutedEventArgs e)
{
ListBoxItem listBoxItem = listBox2.SelectedItem as ListBoxItem;
DataTemplate listBoxTemplate = listBoxItem.ContentTemplate;
StackPanel outerStackPanel = listBoxTemplate.content as StackPanel;
StackPanel innerStackPanel = outerStackPanel.Children[1] as StackPanel;
TextBlock nameBox = innerStackPanel.Children[2] as TextBlock;
nameBox.Visibility = Visibility.Visible;
}
This is my currently my BtnSubmit_click. However,there is some exception on the listBoxTemplate.content part.
I want to make Visibility of LblSecAns to be visible when i clicked on BtnSubmit. I searched ans on google. It is telling me to use Visual tree helper. But i doesn't understand and doesn't know how to apply.
There are two ways to achieve what you want to do here, if I understood correctly.
The first one is like you mentioned with the Visual Tree Helper. Basically every element with a Name, x:Name can be "accessed" using the command: var nameBox = GetTemplateChild("LblSecAns") as TextBox;.
I haven't specifically tested this code on your example (retrieve something from ItemTemplate) but it should work.
The other way and the best one from my point of View is to create a converter. I have been using converters for many reasons, including item's visibility so far and it makes things simpler while keeping the code clean.
A visibility converter would be like:
public class VisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return (bool)value) ? Visibility.Collapsed : Visibility.Visible;
}
public object ConvertBack(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
return Visibility.Visible;
}
}
Then your TextBlock would change to:
<TextBlock x:Name="LblSecAns" HorizontalAlignment="Left" TextWrapping="Wrap" Text="{Binding SecurityAns}" VerticalAlignment="Top" Visibility="{Binding notAnswered, Converter={StaticResource VisibilityConverter}}" Foreground="Black"/>
And finally your button onClick method will simply be:
private void BtnSubmit_Click(object sender, RoutedEventArgs e)
{
ListBoxItem listBoxItem = listBox2.SelectedItem as <<ClassOfTheItem>>;
listBoxItem.notAnswered = false;
}
Don't forget to add the notAnswered property to the item's class <<ClassOfTheItem>> you are binding the listbox to. Since I don't have your code I suggested adding a new property but this step might not be necessary since Visibility can be binded to something else, i.e. the actual answer.

Compare ObservableCollection with Toggle Button listBox?

i have listbox taht fill with list of toggle button in after run the project, if i have observablecollection and i want to compare this ObservableCollection with items in list box where if the item in ObservableCollection exist in listbox i want to make this item (toggle button) checked,
i have tryed to do that but i cant access to toggle button in code behind, becouse the list of toggle buttons show after run the project.
here's my listbox code :
<ListBox x:Name="lbname" ItemsSource="{Binding source}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<ToggleButton x:Name="btnitem" Content="{Binding Name}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ListBox>
and my observableCollection :
IQueryable<items> query = _context.items;
ocitems = new ObservableCollection<items>(query);
In short : How can i compare ObservableCollection items with listbox (Buttons) and if item exist in listbox make the Toggle button that represent the item is checked?
hope this clear.
------------------------------------------ More Detail
i have this list box that show choices for selected item, this listBox filled by ObservableCollection "ocSelectedChoice" :
<ListBox x:Name="lbChoices" ItemsSource="{Binding ocSelectedChoice}" DisplayMemberPath="ChoiceName" HorizontalAlignment="Left" Height="165" VerticalAlignment="Top" Width="186" Margin="567,50,0,0" BorderBrush="#FFC1C1C1" Background="#FFE3E3E3" SelectionMode="Extended">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Height" Value="30"/>
<Setter Property="Background" Value="#FFc4d0df"/>
<Setter Property="BorderBrush" Value="#FFC1C1C1"/>
<Setter Property="BorderThickness" Value="0.8"/>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
when i want to change this item choices, i press the edit button,and will show me windows that has listbox filled by ObservableCollection for all available choices, see the photo, the main problem how to make 'choices 1' lock checked (green one) in choices windows:
<ItemsControl x:Name="icItemGroup" ItemsSource="{Binding PagedSource, ElementName=rdpChoices}" Margin="26,79,0,0" FontWeight="Bold" HorizontalAlignment="Left" Width="506" Height="210" VerticalAlignment="Top" >
<!-- ItemsPanelTemplate -->
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="4" HorizontalAlignment="left" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<!-- ItemTemplate -->
<ItemsControl.ItemTemplate>
<DataTemplate>
<ToggleButton x:Name="tbtnChoices" HorizontalAlignment="Left" VerticalAlignment="Top" FontFamily="tahoma" FontSize="12" Height="45" Width="120" FontWeight="Normal" Margin="0,0,0,5" Background="#FFE8E8E8" BorderBrush="#FFC1C1C1" Foreground="#FF6A6A6A"
Content="{Binding ChoiceName}" TabIndex="{Binding ChoicesID}" Click="tbtnChoices_Click">
<ToggleButton.IsChecked>
<MultiBinding Converter="{StaticResource Choices}">
<Binding Path="ocChoice" RelativeSource="{RelativeSource AncestorType={x:Type Window}}"/>
</MultiBinding>
</ToggleButton.IsChecked>
</ToggleButton>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Converter :
public class ChoicesConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
Choice _choice = values[0] as Choice;
ObservableCollection<Choice> ocChoices = values[1] as ObservableCollection<Choice>;
return ocChoices.Contains(_choice);
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter,
System.Globalization.CultureInfo culture)
{
return null;
}
}
i tried to make this, but sorry still there something unclear for me, please help to solved this issue because it's important for my project.
you should use the multivalue converter to do that i.e bind ToggleButton IsChecked like below:
<ListBox x:Name="lbname" ItemsSource="{Binding source}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<ToggleButton x:Name="btnitem" Content="{Binding Name}">
<ToggleButton.IsChecked>
<MultiBinding Converter="{StaticResource MyConverter}">
<Binding />
<Binding Path="DataContext.ObservableCollectionToCompare" RelativeSource="{RelativeSource AncestorType={x:Type Window}}"/>
</MultiBinding>
</ToggleButton.IsChecked>
</ToggleButton>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ListBox>
Here I am assuming that the observalblecollectin to which you want to compare is a property in your view's DataContext.
MyConverter is the multivalue converter that you need to create.
And in the Convert method of your converter you can compare if the item is there in the collection and return true of false accordingly.
public class MyConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
Item listItem = values[0] as Item;
ObservableCollection<Item> collection = values[1] as ObservableCollection<Item>;
return collection.Contains(listItem);
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter,
System.Globalization.CultureInfo culture)
{
return null;
}
}
oky, i solved it, here's my code :
This is the converter :
public class IsSelectedChoiceConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
bool _check = false;
if (value == null)
return false;
Item currentItem = (Item)value;
if (currentItem.ChoicesinItem.Count == 0)
_check = false;
foreach (var _choicesinItem in currentItem.ChoicesinItem)
{
if (currentItem.CurrentChoiceId == _choicesinItem.ChoicesId)
_check = true;
}
return _check;
}
and xaml code :
<ToggleButton x:Name="tbtnChoices" HorizontalAlignment="Left" VerticalAlignment="Top" FontFamily="tahoma" FontSize="12" Height="45" Width="120" FontWeight="Normal" Margin="0,0,0,5" Background="#FFE8E8E8" BorderBrush="#FFC1C1C1" Foreground="#FF6A6A6A"
IsChecked="{Binding Path=Item,UpdateSourceTrigger=PropertyChanged, Converter={StaticResource IsSelectedChoice}}"
Content="{Binding Item.CurrentChoiceName}" TabIndex="{Binding Item.CurrentChoiceId}" Click="tbtnChoices_Click">
</ToggleButton>
it's work now, Thanks for anyone help me.

How to access items in binded listbox, wp7

I have XAML for WP7:
<ListBox x:Name="lbMain" DataContext="{Binding}" ItemsSource="{Binding Items}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock x:Name="txtName" Text="{Binding name}" />
<ListBox x:Name="lbCars" DataContext="{Binding}" ItemsSource="{Binding cars}" ScrollViewer.VerticalScrollBarVisibility="Disabled">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel x:Name="spnlCars">
<TextBlock x:Name="txtCarName" Text="{Binding name}" />
<ListBox x:Name="lbCarColor" DataContext="{Binding}" ItemsSource="{Binding color}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock x:Name="txtColor" Text="{Binding colorValue}"/>
<Image Name="imgColor"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
My DataContex is set to ViewModel I've created, which is getting data from webservice. Data structure is:
Machines (has: Vehicles[])
-Vehicles (has: name, Cars[], Trucks[],...) ----thats what I'm binding to lbMain
--Cars (has: name, color[],...) ---- for example, color[0]="red"
---colorValue
I also have images resources which I want to put in imgColor.
I don't know hot to:
set each imgColor to get different image from resources depending on the txtColor,
apply bold font to txtCarName if (for example) txtColor.Text="red".
I appreciate any advice and any suggestion.
Create a Converter to convert color name into a BitmapImage.
Example :
class ColorToImageConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
String colorName = (String)value;
switch (colorName.ToLower())
{
case "red":
return new BitmapImage(new Uri("..."));
default:
return new BitmapImage(new Uri("..."));
}
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}

Categories