I am trying to find a control under my xaml in the hub control of windows phone 8.1. It may be the case my method works fine on desktop as I have testest it in wpf before but I am porting it to windows phone and may not work the same.
<Grid>
<Hub Header="Lists" Name="mainHub" >
<HubSection MinWidth="600" Name="lattestLists" Header="New Lists">
<DataTemplate>
<Grid>
<ListBox Background="Transparent" Margin="6" Height="auto" BorderThickness="2" MaxHeight="580" Grid.Row="1" x:Name="listBoxobj" >
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Width="350" >
<Border Margin="5" BorderBrush="White" BorderThickness="1">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Margin="5,0,0,0" Grid.Row="0" x:Name="NameTxt" TextWrapping="Wrap" Text="{Binding Name}" FontSize="28" Foreground="White"/>
<TextBlock Grid.Row="0" Text=">" FontSize="28" HorizontalAlignment="Right" VerticalAlignment="Center" Foreground="White"/>
<TextBlock Margin="5,0,0,0" Grid.Row="1" x:Name="PhoneTxt" TextWrapping="Wrap" Foreground="White" FontSize="18" Text="{Binding PhoneNumber}" />
<TextBlock HorizontalAlignment="Right" Margin="0,0,35,0" Grid.Row="3" x:Name="CreateddateTxt" Foreground="White" FontSize="18" TextWrapping="Wrap" Text="{Binding CreationDate}" />
</Grid>
</Border>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</DataTemplate>
</HubSection>
<HubSection Header="Tech" IsHeaderInteractive="True"
Background="#222222" MinWidth="250">
<DataTemplate>
<StackPanel>
<TextBlock Text="Tech news goes here."
Style="{ThemeResource BodyTextBlockStyle}" />
<TextBlock Text="Click the header to go to the Tech page."
Style="{ThemeResource BodyTextBlockStyle}" />
</StackPanel>
</DataTemplate>
</HubSection>
<HubSection Header="Sports" IsHeaderInteractive="True"
Background="#444444" MinWidth="250">
<DataTemplate>
<StackPanel>
<TextBlock Text="Sports news goes here."
Style="{ThemeResource BodyTextBlockStyle}" />
<TextBlock Text="Click the header to go to the Sports page."
Style="{ThemeResource BodyTextBlockStyle}" />
</StackPanel>
</DataTemplate>
</HubSection>
</Hub>
</Grid>
I am trying to use the following method to find the lsitbox but its not working
ListBox listBoxobjc = FindChildControl<ListBox>(this, "listBoxobj") as ListBox;
listBoxobjc.ItemsSource = DB_ContactList.OrderByDescending(i => i.id).ToList();//Binding DB data to LISTBOX and Latest contact ID can Display first.
This is the method FindChildControl
private DependencyObject FindChildControl<T>(DependencyObject control, string ctrlName)
{
int childNumber = VisualTreeHelper.GetChildrenCount(control);
for (int i = 0; i < childNumber; i++)
{
DependencyObject child = VisualTreeHelper.GetChild(control, i);
FrameworkElement fe = child as FrameworkElement;
// Not a framework element or is null
if (fe == null) return null;
if (child is T && fe.Name == ctrlName)
{
// Found the control so return
return child;
}
else
{
// Not found it - search children
DependencyObject nextLevel = FindChildControl<T>(child, ctrlName);
if (nextLevel != null)
return nextLevel;
}
}
return null;
}
Edit
I debuged the code and its showing the control as null even though I have done the same way as i would
I have replace my method to find children a couple of times during the different versions of Windows Phone / Windows Runtime with this one being the most reliable. Just in case you're not able to spot the mistake you could also try this one and see if it yields better results:
public T FindElementByName<T>(DependencyObject element, string sChildName) where T : FrameworkElement
{
T childElement = null;
var nChildCount = VisualTreeHelper.GetChildrenCount(element);
for (int i = 0; i < nChildCount; i++)
{
FrameworkElement child = VisualTreeHelper.GetChild(element, i) as FrameworkElement;
if (child == null)
continue;
if (child is T && child.Name.Equals(sChildName))
{
childElement = (T)child;
break;
}
childElement = FindElementByName<T>(child, sChildName);
if (childElement != null)
break;
}
return childElement;
}
Also when using this method shortly after creating / loading content I call UpdateLayout beforehand:
this.UpdateLayout();
But be careful - this is not one of the performance-friendliest methods (see also: https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.uielement.updatelayout).
Related
I have a ListView:
<ListView x:Name="All_Staging_ListView"
SelectionMode="Single"
SelectionChanged="All_Staging_ListView_SelectionChanged"
ItemTemplate="{StaticResource All_Staging_ListView_Template}"
BorderThickness="3"
BorderBrush="#005986"
HorizontalAlignment="Stretch"/>
I have a DataTemplate for the ListView:
<Page.Resources>
<DataTemplate x:Key="All_Staging_ListView_Template" x:DataType="local1:All_Staging_Data_Collection_ViewEdit">
<Border BorderBrush="Aqua" BorderThickness="1" Padding="5" Margin="5">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="{x:Bind Metric_ID}" x:Phase="1" FontWeight="ExtraBold" Margin="0,0,5,0"/>
<TextBlock Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="2" Text="{x:Bind Period}" Margin="0,0,0,0"/>
<TextBlock Grid.Row="0" Grid.Column="3" Text="{x:Bind ID}" Margin="25,0,0,0"/>
<Button Grid.Row="0" Grid.RowSpan="2" Grid.Column="4" x:Name="ButtonListViewEdit" Content="Edit this metric" Margin="20,0,0,0" Visibility="Collapsed" Click="ButtonListViewEdit_Click"/>
<TextBlock Grid.Row="1" Grid.Column="0" Text="Name:" FontWeight="Bold" />
<TextBlock Grid.Row="1" Grid.Column="1" Text="{x:Bind Metric_Name}" x:Phase="1" Margin="0,0,20,0"/>
<TextBlock Grid.Row="1" Grid.Column="2" Text="Product:" FontWeight="Bold"/>
<TextBlock Grid.Row="1" Grid.Column="3" Text="{x:Bind Product}"/>
<TextBlock Grid.Row="2" Grid.Column="0" Text="Definition:" FontWeight="Bold"/>
<TextBlock Grid.Row="2" Grid.Column="1" Text="{x:Bind Metric_Definition}" x:Phase="1" Margin="0,0,20,0"/>
<TextBlock Grid.Row="2" Grid.Column="2" Text="Company:" FontWeight="Bold" />
<TextBlock Grid.Row="2" Grid.Column="3" Text="{x:Bind Company}"/>
<TextBlock Grid.Row="3" Grid.Column="0" Text="Goal:" FontWeight="Bold"/>
<TextBlock Grid.Row="3" Grid.Column="1" Text="{x:Bind Goal_Description}" x:Phase="1" Margin="0,0,20,0"/>
<TextBlock Grid.Row="3" Grid.Column="2" Text="System:" FontWeight="Bold"/>
<TextBlock Grid.Row="3" Grid.Column="3" Text="{x:Bind System}"/>
</Grid>
</Border>
</DataTemplate>
</Page.Resources>
When an item in the ListView is 'selected' I would like to make the button 'ButtonListViewEdit' visible!!!!! Edit: (I would like to make the button in the selected item visible only, not in the other unselected items in the ListView).
I don't know the syntax to reference the button within the datatemplate in the 'SelectionChanged' event handler:
private void All_Staging_ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
All_Staging_Data_Collection_ViewEdit listitem = new All_Staging_Data_Collection_ViewEdit();
listitem = (All_Staging_Data_Collection_ViewEdit)All_Staging_ListView.SelectedItem;
Debug.WriteLine($"ListView > SelectionChanged > Metric ID: {listitem.Metric_ID}");
}
I am able to access the values of the bound textblocks, but not the button (to make it visible).
Thank you members of stackoverflow for you help in advance.
Bind the Visibility property of the Button to a property of your All_Staging_Data_Collection_ViewEdit class or get a reference to the Button using the VisualTreeHelper class in your event handler:
private void All_Staging_ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
foreach (object selectedItem in e.AddedItems)
DisplayOrHideButton(selectedItem, true);
foreach (object selectedItem in e.RemovedItems)
DisplayOrHideButton(selectedItem, false);
}
private void DisplayOrHideButton(object item, bool display)
{
ListViewItem container = All_Staging_ListView.ContainerFromItem(item) as ListViewItem;
if (container != null)
{
Button button = FindVisualChild<Button>(container);
if (button != null)
button.Visibility = display ? Visibility.Visible : Visibility.Collapsed;
}
}
private static T FindVisualChild<T>(DependencyObject obj) where T : DependencyObject
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(obj, i);
if (child != null && child is T t)
return t;
else
{
T childOfChild = FindVisualChild<T>(child);
if (childOfChild != null)
return childOfChild;
}
}
return null;
}
I have this code:
<HubSection x:Name="MyHub">
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="200"></RowDefinition>
</Grid.RowDefinitions>
<Image x:Name="MYImage" Source="{Binding image}" Height="50" Width="60" VerticalAlignment="Center"/>
<StackPanel Orientation="Vertical">
<TextBlock TextWrapping="Wrap" Width="200" VerticalAlignment="Center" HorizontalAlignment="Left" Text="{Binding name}"/>
<Button Content="Click me">
</StackPanel>
</Grid>
</DataTemplate>
</HubSection>
But I do not know how to access the text-block, I want to change the foreground color of the text-block in code behind.
XAML:
<Hub x:Name="myHub">
<HubSection x:Name="myHubSection">
<DataTemplate>
<TextBlock x:Name="textbox1" Text="text" Width="300" Height="100">
</TextBlock>
</DataTemplate>
</HubSection>
</Hub>
Code behind:
private void Page_Loaded(object sender, RoutedEventArgs e)
{
var hub_section = FindVisualChildByName<HubSection>(this.myHub, "myHubSection");
var text_box = FindVisualChildByName<WebView>(hub_section, "textbox1");
}
public static T FindVisualChildByName<T>(DependencyObject parent, string name)where T : DependencyObject
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
string controlName = child.GetValue(Control.NameProperty) as string;
if (controlName == name)
{
return child as T;
}
else
{
T result = FindVisualChildByName<T>(child, name);
if (result != null)
return result;
}
}
return null;
}
More detailed information you could refer to How to access a Control inside the data template in C# Metro UI in the code behind
I have comment section with comments and to each comment can be left reply. It looks like this:
<ListBox x:Name="list" ScrollViewer.VerticalScrollBarVisibility="Hidden" ItemsSource="{Binding Comments}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock x:Name="comment" FontSize="15" Foreground="Black" Text="{Binding Text}" TextWrapping="Wrap" Margin="0,1,0,5" Padding="{Binding Depth, Converter={StaticResource LevelToPaddingConverter}, ConverterParameter=15}"/>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<StackPanel Orientation="Horizontal">
<TextBlock x:Name="author" Style="{StaticResource commentInfo}" Text="{Binding UserId, Converter={StaticResource UserIdToUserNameConverter}}" Padding="{Binding Depth, Converter={StaticResource LevelToPaddingConverter}, ConverterParameter=15}"/>
<TextBlock Text="," Style="{StaticResource commentInfo}"/>
<TextBlock x:Name="timeAgo" Style="{StaticResource commentInfo}" Text="{Binding CreatedAt, Converter={StaticResource TimestampToAgoConverter}}"/>
</StackPanel>
<!-- THIS BUTTON --><HyperlinkButton x:Name="reply" Grid.Column="1" FontSize="10" Foreground="Blue" Content="Reply" HorizontalAlignment="Right" Tapped="reply_Tapped"/>
<StackPanel x:Name="replyBox" Visibility="Collapsed" Margin="0,19,0,0">
<TextBox PlaceholderText="Write Comment..." FontSize="11" BorderBrush="Gray" BorderThickness="1" Margin="0,0,0,3" Height="50" GotFocus="TextBox_GotFocus" LostFocus="commentBox_LostFocus" TextWrapping="Wrap"/>
<Button Content="Post Reply" FontSize="12" Background="CornflowerBlue" BorderThickness="0" Style="{StaticResource ButtonStyle1}" Width="75" Height="25" HorizontalAlignment="Right" Tapped="PostCommentButton_Tapped"/>
</StackPanel>
</Grid>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
And when user clicks on that button, TextBox and Button for commentig becomes visible. But if users then clicks reply on another comment, there are two TextBoxes visible(each for the relevant comment). But I want that when user clicks reply to another comment, the previous TextBox would collapse, so only one TextBox is visible at the time. How can I do that?
I found solution. I iterate through all StackPanels in control and find those with name replyBox and then I collapse them.
I did that like this:
foreach (StackPanel sp in FindVisualChildren<StackPanel>(this))
{
if (sp.Name == "replyBox")
{
sp.Visibility = Visibility.Collapsed;
}
}
//and here showing function for the one I wnat to be visible
And FindVisualChildren function looks like this:
public static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
{
if (depObj != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
if (child != null && child is T)
{
yield return (T)child;
}
foreach (T childOfChild in FindVisualChildren<T>(child))
{
yield return childOfChild;
}
}
}
}
I got idea from this answer
my xaml code..
<phone:PhoneApplicationPage.Resources>
<DataTemplate x:Key="DataTemplate1" >
<Border BorderBrush="LightGray" BorderThickness="1" Height="150" Width="500" >
<Grid Width="500" Height="150" Background="White" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.9*"/>
<ColumnDefinition Width="2.5*"/>
<ColumnDefinition Width="1.5*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Image Name="imgitem" Grid.Column="0" Height="Auto" Width="Auto" Source="{Binding ImgSource}" Margin="0,5,4,4" HorizontalAlignment="Left" />
<TextBlock x:Name="txtbindprice" Text="{Binding _PRICE,ConverterCulture=en-IN,StringFormat=C}" TextWrapping="Wrap" Grid.Column="1" Width="350" Foreground="Black" Height="60" Margin="40,70,20,-10"/>
<TextBlock x:Name="txtFinalTotal" Text="{Binding _FinalTotal}" TextWrapping="Wrap" Grid.Column="1" Width="350" Foreground="Red" Height="60" Margin="40,115,20,-10"/>
<TextBlock x:Name="txtITMNAME" Text="{Binding _ITMNAME }" Padding="1" Tap="ItmName_Tapped" TextDecorations="Underline" FontSize="24" TextWrapping="Wrap" Grid.Column="1" FontWeight="Normal" TextTrimming="WordEllipsis" Foreground="OrangeRed" Width="Auto" Height="150" Margin="30,25,10,-10"/>
<CheckBox Grid.Column="2" Grid.Row="0" Background="Black" Foreground="Black" BorderThickness="4" BorderBrush="Red" Margin="10,20,-15,10" Checked="CheckBox_Checked" Unchecked="CheckBox_UnChecked" />
</Grid>
</Border>
</DataTemplate>
<ListBox Height="Auto" Name="lstbxmanual" SelectionMode="Extended" ItemTemplate="{StaticResource DataTemplate1 }" Width="475" Margin="2,192,0,-39" Background="White" HorizontalAlignment="Left" Grid.RowSpan="2">
</ListBox>
I want to access textblocks inside listbox based on selected index
accessing textblock
string a =txtbindprice.text
wont work as they are inside data template of listbox..
I came across visual child tree methods and some other examples..i cant find much info..
please help me regarding this...
The following method finds currently selected list-box item:
private ListBoxItem FindSelectedListBoxItem(DependencyObject control)
{
int childNumber = VisualTreeHelper.GetChildrenCount(control);
for (int i = 0; i < childNumber; i++)
{
DependencyObject child = VisualTreeHelper.GetChild(control, i);
FrameworkElement fe = child as FrameworkElement;
// Not a framework element or is null
if (fe == null) return null;
if (child is ListBoxItem && ((ListBoxItem)child).IsSelected)
{
// Found the control so return
return (ListBoxItem)child;
}
else
{
// Not found it - search children
ListBoxItem nextLevel = FindSelectedListBoxItem(child);
if (nextLevel != null)
return nextLevel;
}
}
return null;
}
Below method finds any child control with a certain name from a given root control:
private DependencyObject FindChildControl<T>(DependencyObject control, string ctrlName)
{
int childNumber = VisualTreeHelper.GetChildrenCount(control);
for (int i = 0; i < childNumber; i++)
{
DependencyObject child = VisualTreeHelper.GetChild(control, i);
FrameworkElement fe = child as FrameworkElement;
// Not a framework element or is null
if (fe == null) return null;
if (child is T && fe.Name == ctrlName)
{
// Found the control so return
return child;
}
else
{
// Not found it - search children
DependencyObject nextLevel = FindChildControl<T>(child, ctrlName);
if (nextLevel != null)
return nextLevel;
}
}
return null;
}
Now you can use the first method to get currently selected ListBoxItemand then pass it to the second method to retrieve any control inside this ListBoxItem (e.g. txtbindprice):
ListBoxItem item = FindSelectedListBoxItem(this);
TextBlock txtPrice = FindChildControl<TextBlock>(item , "txtbindprice") as TextBlock;
string a = txtPrice.Text;
Update
You can add SelectionChanged event to your ListBox like this:
<ListBox Height="Auto" Name="lstbxmanual" SelectionChanged="OnSelectionChanged">
</ListBox>
And then retrieve a certain TextBlock.Text (e.g. txtbindprice) this way:
public void OnSelectionChanged(object sender, SelectionChangedEventArgs args)
{
ListBoxItem item = FindSelectedListBoxItem((ListBox(sender)));
TextBlock txtPrice = FindChildControl<TextBlock>(item , "txtbindprice") as TextBlock;
string a = txtPrice.Text;
}
Last year I made an app for Windows Phone 8, containing a LongListSelector with a unique first and last item template, as described here:
LongListSelector different item template for first and last item
I recently updated the app to Windows Phone 8.1 Store and this functionality broke. Here's my class (the only difference from the post being, that I'm using a ListView instead of a LongListSelector for Windows Phone 8.1 Store, since LongListSelector is not a part of the Windows Phone 8.1 Store framework):
public abstract class TemplateSelector : ContentControl
{
public abstract DataTemplate SelectTemplate(object item, int index, int totalCount, DependencyObject container);
protected override void OnContentChanged(object oldContent, object newContent)
{
base.OnContentChanged(oldContent, newContent);
var parent = GetParentByType<ListView>(this);
var index = (parent.ItemsSource as IList).IndexOf(newContent);
var totalCount = (parent.ItemsSource as IList).Count;
ContentTemplate = SelectTemplate(newContent, index, totalCount, this);
}
private static T GetParentByType<T>(DependencyObject element) where T : FrameworkElement
{
T result = null;
DependencyObject parent = VisualTreeHelper.GetParent(element);
while (parent != null)
{
result = parent as T;
if (result != null)
{
return result;
}
parent = VisualTreeHelper.GetParent(parent);
}
return null;
}
}
The problem is that this:
DependencyObject parent = VisualTreeHelper.GetParent(element);
of the GetParentByType function returns null for some reason. Anyone knows why or have an alternative solution?
Below is my XAML code(with a few xmlns's removed). The DataTrigger is there because sometimes a unique first item template is enough (controlled by the LoadMore property of the ViewModel, which is a bool).
<controls:WP81Page
xmlns:core="using:Microsoft.Xaml.Interactions.Core"
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<controls:WP81Page.Resources>
<DataTemplate x:Key="first">
<Grid HorizontalAlignment="Left" Width="Auto" Height="200">
<Border BorderThickness="1" BorderBrush="Black" Visibility="{Binding NoLargeImage, Converter={StaticResource BoolToVisibilityConverter}}" >
<Image Source="/Images/default-image.png" Stretch="UniformToFill" />
</Border>
<Border BorderThickness="1" BorderBrush="Black" Visibility="{Binding NoLargeImage, Converter={StaticResource BoolToVisibilityConverterReverse}}" >
<Image Source="{Binding LargeImageUrl}" Stretch="UniformToFill" />
</Border>
<StackPanel VerticalAlignment="Bottom" Background="#7F000000" >
<TextBlock Text="{Binding Header}" VerticalAlignment="Center" TextWrapping="Wrap" Foreground="White" FontWeight="Bold" Margin="15,0,15,15"/>
</StackPanel>
</Grid>
</DataTemplate>
<DataTemplate x:Key="default">
<StackPanel Orientation="Horizontal" Margin="0,10,0,0" Height="105" Width="Auto">
<Border BorderThickness="1" BorderBrush="Black" Margin="0,2" Visibility="{Binding NoSmallImage, Converter={StaticResource BoolToVisibilityConverter}}" >
<Image Source="/Images/default-image.png" Width="130" Height="100" Stretch="UniformToFill" />
</Border>
<Border BorderThickness="1" BorderBrush="Black" Margin="0,2" Visibility="{Binding NoSmallImage, Converter={StaticResource BoolToVisibilityConverterReverse}}">
<Image Source="{Binding SmallImageUrl}" Width="130" Height="100" Stretch="UniformToFill"/>
</Border>
<StackPanel Orientation="Vertical" Width="300" Margin="8,0,0,0">
<TextBlock Text="{Binding Header}" TextWrapping="Wrap" FontWeight="Bold" />
<TextBlock Margin="0,3,0,0" Text="{Binding DisplayDate}" TextWrapping="Wrap" Foreground="#FFB9B9B9" FontSize="16" />
</StackPanel>
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="last">
<TextBlock Text="hent flere nyheder" FontSize="25" Margin="0,20" TextWrapping="Wrap" VerticalAlignment="Center" HorizontalAlignment="Center" Height="75" />
</DataTemplate>
<DataTemplate x:Key="UniqueFirstTemplateSelector">
<common:UniqueFirstTemplateSelector Content="{Binding}" First="{StaticResource first}" Default="{StaticResource default}" HorizontalAlignment="Stretch"/>
</DataTemplate>
<DataTemplate x:Key="UniqueFirstAndLastTemplateSelector">
<common:UniqueFirstAndLastTemplateSelector Content="{Binding}" First="{StaticResource first}" Default="{StaticResource default}" Last="{StaticResource last}" HorizontalAlignment="Stretch"/>
</DataTemplate>
</controls:WP81Page.Resources>
<controls:WP81Page.DataContext>
<viewModels:NewsViewModel/>
</controls:WP81Page.DataContext>
<Grid x:Name="LayoutRoot" Style="{Binding Source={StaticResource Background}}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ProgressBar Grid.Row="0" VerticalAlignment="Top" IsIndeterminate="True" Background="Transparent" Foreground="White" Visibility="{Binding IsLoading, Converter={StaticResource BoolToVisibilityConverter}}" />
<StackPanel Grid.Row="0" Margin="12,17,0,28">
<TextBlock Text="NYHEDER" FontSize="35" FontWeight="Bold" Style="{StaticResource PhoneTextNormalStyle}"/>
</StackPanel>
<Grid x:Name="ContentPanel" Grid.Row="1">
<controls:WP81ListView x:Name="listSelector" Margin="22,0" Grid.Row="2" ItemsSource="{Binding News}" Command="{Binding NewsEntrySelectedCommand}" >
<interactivity:Interaction.Behaviors>
<core:DataTriggerBehavior Binding="{Binding LoadMore}" Value="True">
<core:ChangePropertyAction TargetObject="{Binding ElementName=listSelector}"
Value="{StaticResource UniqueFirstAndLastTemplateSelector}"
PropertyName="ItemTemplate" />
</core:DataTriggerBehavior>
<core:DataTriggerBehavior Binding="{Binding LoadMore}" Value="False">
<core:ChangePropertyAction TargetObject="{Binding ElementName=listSelector}"
Value="{StaticResource UniqueFirstTemplateSelector}"
PropertyName="ItemTemplate" />
</core:DataTriggerBehavior>
</interactivity:Interaction.Behaviors>
</controls:WP81ListView>
</Grid>
</Grid>
</controls:WP81Page>
Thank you in advance.
EDIT
Alright, so what I want is not for the first and last item to be unique all the time. I'm making a news feed where the last item is only unique when there are more news entries to load (when the last item are clicked, more news entries are added to the ListView). If however, the end of the news entries are reached, the last item must not be unique (hence the combination with interactivity).
ListView has a property called ItemTemplateSelector which accepts objects based on DataTemplateSelector. So you need to change a couple of things to get it to work.
First of all, the definition of your template selector. It needs to be based on DataTemplateSelector and override method called SelectTemplateCore. It takes an object which is a ListViewItem. At that point you can go up the VisualTree to get the ListView and choose the DataTemplate based on index.
public class MyTemplateSelector : DataTemplateSelector
{
public DataTemplate First { get; set; }
public DataTemplate Default { get; set; }
public DataTemplate Last { get; set; }
protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
{
var listViewItem = container as ListViewItem;
var listView = GetParentByType<ListView>(listViewItem);
var index = (listView.ItemsSource as IList).IndexOf(item);
var totalCount = (listView.ItemsSource as IList).Count;
if (index == 0)
return First;
else if (index == totalCount - 1)
return Last;
else
return Default;
}
private T GetParentByType<T>(DependencyObject element) where T : FrameworkElement
{
T result = null;
DependencyObject parent = VisualTreeHelper.GetParent(element);
while (parent != null)
{
result = parent as T;
if (result != null)
{
return result;
}
parent = VisualTreeHelper.GetParent(parent);
}
return null;
}
}
Then, you need to create an instance of it in static resources
<local:MyTemplateSelector x:Key="SelectingTemplate"
First="{StaticResource first}"
Default="{StaticResource default}"
Last="{StaticResource last}" />
with the First, Default and Last DataTemplates, just like you did before.
The last step is to apply it to the ListView you're using.
<ListView ItemsSource="{Binding SomeItemsSource}"
ItemTemplateSelector="{StaticResource SelectingTemplate}" />
And that's it!