Bind outside ItemsSource of DataTemplate, Windows phone - c#

In my Windows Phone 8 I have LongListSelector and ItemTemplate specified for that. In code behind I set the ItemsSource for this LongListSelector. In item template I want to bind value to outside ItemsSource. How to do that?
<DataTemplate x:Key="template">
<TextBlock Text="{Binding name}"/>
<TextBlock Text="{Binding country}"/>
</DataTemplate>
...
<phone:LongListSelector x:Name="list" ItemTemplate="{StaticResource template}">
</phone:LongListSelector>
C#
string country = "Japan";
this.list.ItemsSource = items;
So how to bind country to outside ItemsSource? The country is accessor in my "code behind" phoneApplicationPage.

It would be best that you make your models so that inside template you have to bind only to that item model.
Anyway it is possible to bind also outside of itemSource:
xaml:
<phone:PhoneApplicationPage.Resources>
<DataTemplate x:Key="ItemTemplate">
<StackPanel>
<TextBlock Text="{Binding Name}"/>
<!-- this binds to the layoutRoot's dataContext, which can be setted to be "code behind" -->
<TextBlock Text="{Binding DataContext.Outside, ElementName=LayoutRoot}"/>
</StackPanel>
</DataTemplate>
</phone:PhoneApplicationPage.Resources>
<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot">
<phone:LongListSelector ItemsSource="{Binding Items}"
IsGroupingEnabled="False"
ItemTemplate="{StaticResource ItemTemplate}">
</phone:LongListSelector>
</Grid>
In cs you have of course properties:
public ObservableCollection<Model> Items{get; set;}
public string Outside { get; set; }
Also layoutRoot's datacontext should be setted somewhere in cs:
LayoutRoot.DataContext = this;

Related

How to (is it possible to) set property of user control from outside?

This is my XAML:
<UserControl x:Class="SearchResultsBox">
<ListBox ItemsSource="{Binding SearchResults}" SelectedItem="{Binding Selected}"
Style="{StaticResource ListBoxStyle1}"
ItemContainerStyle="{StaticResource SearchItemContainerStyle}"
Background="{StaticResource DefaultBackground}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Background="Transparent">
<local:Forecast_SearchResults_ListView_Data/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</UserControl x:Class="SearchResultsBox">
I want to be able to reuse this listbox and just slap on a new datatemplate from the external context:
<local:SearchResultsBox>
<DataTemplate = {ForecastDataTemplate}/>
</local>
And it will put this DataTemplate into the ListBox.ItemTemplate property. Is this even possible? If so, how? If not, is there another way to achieve a similar effect?
you may use as follows
<local:SearchResultsBox ItemTemplate="{StaticResource ForecastDataTemplate}" />
and you can wire up the property to the underlying ListBox
eg
add a name to listbox
<ListBox x:Name="list" ... />
add a property wiring
public DataTemplate ItemTemplate
{
get { return list.ItemTemplate;}
set { list.ItemTemplate = value;}
}

Get parent datacontext brush from inside a listview

I got the following:
<ListView ItemsSource="{Binding Path=Items}">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Name}" Foreground="{Binding Path=GridTextColor}"></TextBlock>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
The datacontext looks like this:
class{
items = List with items (each row has a name property)
GridTextColor = Brush
}
I bind the listview with all items. Each item contains a name and that name shows up nicely in the listview.
The problem is that i want all items inside the DataTemplate to have the Foreground set to the brush.
With the code above that is not possible since when i am inside the DataTemplate i bind to the items that are sent in.
Question, how can i bind to the "parent datacontext" to get the correct foreground color?
You can use RelativeSource in your binding to get parent's DataContext.
<TextBlock Text="{Binding Path=Name}"
Foreground="{Binding Path=DataContext.GridTextColor,
RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType=ListView}}"/>
Or Set x:Name on ListView and bind using ElementName:
<ListView x:Name="myListView">
....
<TextBlock Text="{Binding Path=Name}"
Foreground="{Binding DataContext.GridTextColor,
ElementName=myListView}" />
....
</ListView>

Binding listbox to object without window datacontext

I would like to bind my listbox to an object without the wpf window binding to a datacontext:
<ListBox Height="Auto" HorizontalAlignment="Left" Margin="0,0,0,0" Name="lstb_logFiles" VerticalAlignment="Stretch" Width="100" SelectionChanged="lstb_threadList_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding dateName,StringFormat=\{0\}}" Foreground="Orange" Margin="10,3,0,3" Width="80" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
And here is where I setup the binding
public ObservableCollection<FileLog> _logFiles = new ObservableCollection<FileLog>();
lstb_logFiles.DataContext = _logFiles;
This doesn't work, my _logFiles definitely have object in it, but lstb_logFiles does not show any items. What am I doing wrong?
For ListBox to populate its item, you should set ItemsSource and not DataContext.
It should be:
lstb_logFiles.ItemsSource = _logFiles;
and not
lstb_logFiles.DataContext = _logFiles;
you have to set the itemssource to "self"
<ListBox ItemsSource="{Binding}"/>
or instead of setting the datacontext you can set the itemssource directly
public ObservableCollection<FileLog> _logFiles = new ObservableCollection<FileLog>();
lstb_logFiles.ItemsSource= _logFiles;

Listview bound via ElementName stays empty

I'm stuck again at some data-binding issue.
This time I want to bind a ListView to the SelectedItem of a GridView. I already suceed with this type of data-binding but now my ListView, which should show some details about my selected item in my GridView just stays empty. There are no items in it although they should exist.
The GridView binds just fine at the property in my MainViewModel.Substituting the ElementName attribute with x:Resouces doesn't seem to be an option, because it doesn't work either.
The source view:
<GridView x:Name="gridViewOrderYears"
ItemsSource="{Binding SelectedCustOrders, Mode=TwoWay}"
HorizontalAlignment="Left"
Grid.Row="1"
VerticalAlignment="Top"
Width="316"
Height="63"
Margin="657,316,0,0"
SelectionMode="Single">
<GridView.ItemTemplate>
<DataTemplate>
<Grid>
<Border BorderThickness="1" BorderBrush="Aquamarine">
<StackPanel>
<TextBlock Text="{Binding Year}" FontSize="20"/>
<TextBlock Text="{Binding OrderCount}"/>
</StackPanel>
</Border>
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
this View doesnt bind:
<ListView HorizontalAlignment="Left"
Height="231"
Margin="657,401,0,0"
Grid.Row="1"
VerticalAlignment="Top"
Width="316"
DataContext="{Binding SelectedItem, ElementName=gridViewOrderYears}">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding DoneOrders.Order_Date, ElementName=gridViewOrderYears}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
SelectedCustOrders porperty is an IList<OrderYears>.
OrderYears is following data value object defined in my MainViewModel:
public class OrderYears
{
public int? Year { get; set; }
public IList<Orders> DoneOrders { get; set; }
public int OrderCount { get; set; }
}
I think the problem is in the ListView binding, because you try to bind to a property named "Orders", which does not exist in the OrderYears object. You have a property named DoneOrders which you can bind to (don't confuse the property name with the type of elements inside the list!), but if you bind a TextBlock to a IList you will just get the guid for the IList object.
Try something like this, replacing you ListView with a ListBox (which is enough for what you are trying to do here):
<ListBox DataContext="{Binding ElementName=gridViewOrderYears,
Path=SelectedItem.DoneOrders}"
DisplayMemberPath="Order_Date"/>
There is no need to create a template, the items inside the ListBox will be displayed like a TextBlock. Note that you can benefit from binding to nested properties like MainProperty.SubProperty.
Let me know if this was helpful, bindings can be such a headache when you are starting...
Finally I got it.
After hours of trial-and-error finally substituting DataContext with ItemsSource did the trick... Sometimes things are easier than you think :)

Databinding CustomControls within PivotControls

I'm trying to use a PivotControlPage to control the paging of an object with a List
My current attempt is like so
<controls:Pivot x:Name="quizPivot" Title="MY APPLICATION" ItemsSource="{Binding Questions}" SelectedIndex="1" >
<controls:PivotItem Header="{Binding QuestionTitle }">
<Grid>
<local:Text5Control DataContext="{Binding .}"></local:Text5Control>
</Grid>
</controls:PivotItem>
</controls:Pivot>
I want the pivot control to control the "next" and "previous" actions and pass that current item to the DataContext of my custom control.
I'm doing this slightly wrong I think, but i'm setting the DataContext of the pivotcontrol and the currentitem in the code behind.
this is where i set the datacontext for the pivot control
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
quiz = new Quiz();
quiz.Questions = loadQuestions() // loads questions from file
quizPivot.DataContext = quiz;
}
I changed the xaml to look like this.
<controls:Pivot x:Name="quizPivot" Title="Mensa" SelectedIndex="1" DataContext="{Binding quiz}" ItemsSource="{Binding Questions}">
<controls:Pivot.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding QuestionTitle}" />
</DataTemplate>
</controls:Pivot.HeaderTemplate>
<controls:Pivot.ItemTemplate>
<DataTemplate>
<Grid>
<local:Text5Control DataContext="{Binding .}"></local:Text5Control>
</Grid>
</DataTemplate>
</controls:Pivot.ItemTemplate>
</controls:Pivot>
What I was missing is the use of templates for the data. PivotItem is only applicable for static items.

Categories

Resources