I am developing UWP App, I have a Listview bind with a class, wherein upto 10 items. Listview have a DataTemplate and a Usercontrol is inside this DataTemplate.
I want to click on any item so the animation (storyboard) should start and the ColorBand should expand toward right and when I click on another item now the expanded (previously clicked) ColorBand should collapse and the current clicked item's ColorBand should expand.
This approach can be possible if I put this ColorBand inside the Listviewitem Style and use the Visual State Manager, but actually I need to put the border color and corner radius etc dynamically via class in runtime and also have the Edit option if the user want to change the color etc... so it must be via binding.
So I need to run animation on currently clicked item and the previously clicked item simultaneously. plz help, I m stuck due to this.
<VisualStateGroup x:Name="SelectionStates">
<VisualState x:Name="Unselected"/>
<VisualState x:Name="Selected">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="InnerGrid">
<DiscreteObjectKeyFrame KeyTime="0" Value="{Binding ColorBand}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentPresenter">
<DiscreteObjectKeyFrame KeyTime="0" Value="White"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="FontWeight" Storyboard.TargetName="ContentPresenter">
<DiscreteObjectKeyFrame KeyTime="0" Value="ExtraBold"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
Using SelectionChanged method
private async void Selectionchanged(object sender, SelectionChangedEventArgs args)
{
foreach(var item in args.AddedItems)
{
ListViewItem item = (sender as ListView).ContainerFromItem(item) as ListViewItem;
// you will get slected item here. Use that item to get listbox item
}
if(args.RemovedItems!=null)
{
foreach(var item in args.RemovedItems)
{
//You will get previosly selcted item here
ListViewItem item = (sender as ListView).ContainerFromItem(item) as ListViewItem
}
}
}
I think the most easiest way to get previously clicked item is via c# code with two properties. And than you can do with this item whatever you want. Use selection changed event and when it raise you should add this selected item to a new properties something like this:
public object PreviouslySelectedItem {get; set;}
public object CurrentlySelectedItem
{
get;
set{
PreviouslySelectedItem = CurrentlySelectedItem ;
CurrentlySelectedItem = value;
}
}
private async void Selectionchanged(object sender, SelectionChangedEventArgs args)
{
CurrentlySelectedItem = (sender as ListBox).SelectedItem;
// some handling with null cases and etc.
// now you can apply your animation on your two items
}
Related
I have one datgrid with no. of columns like:
<s:DataGrid id="cpDataGrid" dataProvider="{arrList}">
<s:columns>
<mx:ArrayList>
<mx:source>
<s:GridColumn headerText="Name" dataField="name" editable="false"/>
<s:GridColumn headerText="Age" datafield="age" editable="false"/>
<s:GridColumn headerText="Test" dataField="test" editable="false" />
<s:GridColumn width="100" headerText="Result" dataField="result" >
</mx:source>
</mx:ArrayList>
</s:columns>
</s:DataGrid>
In the above datagrid result column is editable. I have make function when user done entering value in that column as following:
protected function onCreationCompleteHandler(event:FlexEvent):void
{
cpDataGrid.addEventListener(GridItemEditorEvent.GRID_ITEM_EDITOR_SESSION_SAVE, onSave);
}
private function onSave(event:GridItemEditorEvent):void
{
var name:String = event.currentTarget.selectedItem.name;
}
Now, I will get name and other field value when edit end. But i need Result text. Means Whatever user entered text in that field.
Like suppose user enter 50 in result column then how can i got that value?
Any help will greatly appreciated.
For spark.DataGrid you need to create custom class based on spark.DataGrid and override method endItemEditorSession. In it you can access DataGrid's property itemEditorInstance.
If you would use mx.DataGrid, you could use DataGridEvent.ITEM_EDIT_END event in combination with itemEditorInstance property of DataGrid.
// register listener
cpDataGrid.addEventListener(DataGridEvent.ITEM_EDIT_END, onItemEditEnd);
...
// listener
private function onItemEditEnd(event:DataGridEvent):void {
// at this point itemEditorInstance is still available, so you can get entered value from it
// if itemEditorInstance is TextInput
var enteredValue:String = TextInput(cpDataGrid.itemEditorInstance).text;
}
In my WinRT/Phone 8.1 app I have a form with a number of Grids (serving as wrappers) each containing two or more TextBlocks. I want to show only data that is available, meaning that if the content TextBlock of a particular Grid is empty I want to hide the entire Grid.
For instance:ยด
<Grid x:Name="NameSection">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0"
x:Name="NameLabel"
Text="Name:" />
<TextBlock Grid.Row="1"
x:Name="Name"
Text="{Binding Name}" />
</Grid>
If the Name TextBlock is empty, the entire Grid's visibility should be collapsed.
Adding logic for this either to code behind or (worse) the ViewModel could get messy for this long form, so I wonder if I can achieve this using XAML and styles. How can it be done in WinRT? Can I style the Grid such that it's visibility is based on the content in one of its subviews?
Converter
public class NullToVisibilityConverter: IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
return value == null ? Visibility.Collapsed: Visibility.Visible;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
then use it like this
<Grid x:Name="NameSection" Visibility={Binding Name, Converter={StaticResource MyNullConverter}}>
edit:
you can add string.IsNullOrEmpty(value as string) insted of value == null, if you want to check empty strings as well
I have a LongListSelector with a ItemTemplate like this:
<LongListSelector.ItemTemplate>
<DataTemplate>
<StackPanel>
Here I have a lot of elements that are always the same.
.
.
.
and one that varies
</StackPanel>
</DataTemplate>
</LongListSelector.ItemTemplate>
I know how to use this TemplateSelector class to change all the content inside the ItemTemplate depending o the item type.
My question is, how can use the template selector to change only the one item that varies so I dont need to repeat the whole lot of other elements.
I have tried using a ContentControl and ContentPresenter inside de StackPanel with no success
You're going to want to create a data trigger in your XAML to check whether each item is the one you're looking for.
This SO question is relevant enough to get you on the right track. It'll end up looking something like this:
<Style TargetType="TabItem">
<Style.Triggers>
<!-- Styling for elements that are NOT the last item -->
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Converter={StaticResource LastItemConverter}}" Value="False">
<Setter Property="Template">
<Setter.Value>
.
.
.
</Setter.Value>
</Setter>
</DataTrigger>
<!-- Styling for elements that are the last item -->
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Converter={StaticResource LastItemConverter}}" Value="True">
<Setter Property="Template">
<Setter.Value>
.
.
.
</Setter.Value>
</Setter>
</DataTrigger>
The Converter looks something like this - depending on what UI element you're binding.
public class IsLastItemInContainerConverter : IValueConverter
{
public object Convert(object value, Type targetType,
object parameter, CultureInfo culture)
{
DependencyObject item = (DependencyObject)value;
TabControl tc = (TabControl)TabControl.ItemsControlFromItemContainer(item);
// Return true for the first and last element
// (so they are similarly styled compared to other elements).
if (tc.ItemContainerGenerator.IndexFromContainer(item) == tc.Items.Count - 1) {
return true;
}
else if (tc.ItemContainerGenerator.IndexFromContainer(item) == 0)
{
return true;
}
else
{
return false;
}
}
Hope that helps.
I want to implement a Listbox binding directly and here is the code i used in WPF syntax
<ListBox Name="lboxData" ItemsSource="{Binding}">
<ListBox.ItemTemplate >
<DataTemplate>
<StackPanel>
<ToggleButton x:Name="toggleChild" Style="{StaticResource ChapterHeadingStyle}"
IsChecked="{Binding IsSelected, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}}" // This is what i have to change . I want to set it based on the status of the ListBoxItem & Given code is the one i used in WPF app
/>
<ListBox Visibility="{Binding IsChecked, ElementName=toggleChild, Converter={StaticResource boolToVis}}" ItemsSource="{Binding pages}" Margin="10,0,0,0" >
<ListBox.ItemTemplate >
<DataTemplate>
//here is displaying child items one by one ..
</DataTemplate>
</ListBox.ItemTemplate >
</ListBox>
</ListBox.ItemTemplate >
</DataTemplate>
</StackPanel>
</ListBox>
The problem is that in WP8 RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem} is not supported . So how can i achieve the same thing in WP8. I want to set the toggle button as Checked if the container ListboxItem is selected , else i want to set the IsChecked as False.
I'll start by writing a comparer class
public class ElementComparer : FrameworkElement
{
public object Element1
{
get { return (object)GetValue(Element1Property); }
set { SetValue(Element1Property, value); }
}
// Using a DependencyProperty as the backing store for Element1. This enables animation, styling, binding, etc...
public static readonly DependencyProperty Element1Property =
DependencyProperty.Register("Element1", typeof(object), typeof(ElementComparer), new PropertyMetadata(null, UpdateResult));
public object Element2
{
get { return (object)GetValue(Element2Property); }
set { SetValue(Element2Property, value); }
}
// Using a DependencyProperty as the backing store for Element2. This enables animation, styling, binding, etc...
public static readonly DependencyProperty Element2Property =
DependencyProperty.Register("Element2", typeof(object), typeof(ElementComparer), new PropertyMetadata(null, UpdateResult));
public bool Result
{
get { return (bool)GetValue(ResultProperty); }
set { SetValue(ResultProperty, value); }
}
// Using a DependencyProperty as the backing store for Result. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ResultProperty =
DependencyProperty.Register("Result", typeof(bool), typeof(ElementComparer), new PropertyMetadata(false, OnResultChanged)); //added changed handler
private static void OnResultChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
ElementComparer ec = d as ElementComparer;
//if true then set the element 2 to element 1 of the comparer otherwise null
ec.Element2 = ((bool)e.NewValue) ? ec.Element1 : null;
}
private static void UpdateResult(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
ElementComparer ec = d as ElementComparer;
ec.Result = object.ReferenceEquals(ec.Element1, ec.Element2);
}
}
then I'll bind IsChecked from togglebutton to the Result of ElementComparer and will bind the Element1 and Element2 of the comaprer with the current item and the SelectedItem of lboxData (ListBox)
<ListBox Name="lboxData" ItemsSource="{Binding}">
<ListBox.ItemTemplate >
<DataTemplate>
<StackPanel>
<!--added Mode=TwoWay to binding of Element2-->
<local:ElementComparer x:Name="ElementComparer"
Element1="{Binding}"
Element2="{Binding SelectedItem, ElementName=bookTOCBox, Mode=TwoWay}" />
<!--removed Mode=OneWay from binding of IsChecked and added Mode=TwoWay-->
<ToggleButton x:Name="toggleChild" Content="{Binding name}"
Style="{StaticResource ChapterHeadingStyle}"
IsChecked="{Binding Result, ElementName=ElementComparer, Mode=TwoWay}"/>
...
</StackPanel>
the trick is to compare the selected item of the list to the current item to detect if it is selected as long as the name of parent listbox is "lboxData", this will work in WP8 too
Update summary
Removed one way binding from IsChecked property of toggle to Result of ElementComparer
Added two way binding to SelectedItem to Element2 of ElementComparer
added property changed handler for the Result property in ElementComparer
when the result is changes and is true (toggle is checked) push the value of Element1 to Element2
since the Element2 is bound to SelectedItem it force other items's result to false hence turn off the toggle and collapse the child list
added Mode=TwoWay to IsChecked property of toggle as seems quit unpredictable without it
Extras
additionally if you don't want to see ugly looking blue selection in list items then you may add the following to your resources too
<Style TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border Background="Transparent">
<ContentPresenter/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I am new to WPF technology. i am using MVVM architecture.
I want to change the background of textblock based on viewmodel's attribute.
e.g If i am using 'brush' object, I want to bind it to background color of textblock.
<TextBlock Margin="0,1"
HorizontalAlignment="Center"
FontFamily="Arial"
FontSize="16"
Text="{Binding Line}"
TextWrapping="Wrap"
Background="{Binding brushobj}"/>
How to implement it?
You could define it like this, inside your ViewModel.
private Brush _brushobj;
/// <summary>
/// Gets or sets the BrushObject.
/// </summary>
public Brush BrushObj
{
get
{
return _brushobj;
}
set
{
// Set value
_brushobj = value;
// Notify UI that the value has changed.
RaisePropertyChanged("BrushObj");
// OnPropertyChanged("BrushObj"); // Use the appropriate function to notify the UI.
}
}
Then simply set the value with something like this:
BrushObj = (Brush)new BrushConverter().ConvertFromString("Green");
Last you bind it to your View like you did in your question:
Background="{Binding BrushObj}"
Edit: I tried to make a project myself just to verify that this was indeed working and the following code worked fine. If it's still not working it's more likely to be something with your MVVM setup causing problem.
MainWindowViewModel:
namespace WpfApplication1
{
public class MainWindowViewModel : ObservableObject
{
private Brush _brushobj = (Brush)new BrushConverter().ConvertFromString("Red");
public Brush BrushObj
{
get
{
return _brushobj;
}
set
{
_brushobj = value; // Set value
RaisePropertyChanged("BrushObj"); // Notify UI that the value has changed.
}
}
}
}
MainWindow:
<Window x:Class="WpfApplication1.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>
<TextBlock Margin="0,1"
VerticalAlignment="Center"
HorizontalAlignment="Center"
FontFamily="Arial"
FontSize="16"
Text="Testing a lot of stuff here! important stuff!"
TextWrapping="Wrap"
Background="{Binding BrushObj}"/>
</Grid>
</Window>