Simple ListView databinding issue - wpf

I guess there is something trivial I am overlooking here. The Window has a DataContext and everything else in the window databinds nicely. The same RecentItems is also databound to a Menu without any problems.
My XAML:
<ListView ItemsSource="{Binding Path=RecentItems}">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock>◾ <Hyperlink Command="{Binding Path=Command}"><TextBlock Text="{Binding Path=Header}"/></Hyperlink></TextBlock>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
WPF renders:
I should perhaps also mention the ListView is embedded inside a FlowDocument via a BlockUIContainer.
EDIT: I changed the XAML so that I use a Run inside the TextBlock instead - I can understand a nested TextBlock is not a good idea (although then I expect a runtime error at least) - but that gives me another binding error saying that I cannot bind to a readonly property - even if I change the Mode to OneWay.

Related

WPF TabControl, switching to another TabItem does not work, sticks to first TabItem

I have a control that contains following XAML code. It works fine excepted that I caInnot switch to another TabItem. I read that TabControl virtualizes the TabItem, I suspect the strange behaviour, namely that I cannot get to display any other TabItem as the first one, is related to this.
<TabControl ItemsSource="{Binding Items}">
<TabControl.ItemTemplate>
<DataTemplate> <!-- header -->
<TextBlock Text="{Binding Title}"></TextBlock>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate x:Shared="False"> <!-- tabitem content -->
<controls:ItemControl Item="{Binding}" />
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
I tried to set the x:Shared attribute of the DataTemplate to False but has not the expected effect. Is there a way to reach this without going the way of using a custom style and replacing the TabControl with an ItemsControl. I mean the functionality of TabControl is what I would like, I would like to simply use it with ItemsSource binding...
This behaviour will happen if you are binding to a collection that has duplicate objects in it.
Duplication can occur due to having added an object multiple times or because equality has been redefined for the objects in question.

Silverlight Treeview SelectedItem TwoWay binding causing error in blend

I have a Treeview in a Silverlight 4 project, and I want to bind to its SelectedItem. When I do a binding to SelectedItem (Mode=TwoWay) its throwing an error in blend because SelectedItem is readonly, which is causing my XAML to not render. I don't ever want to SET the SelectedItem property, I just want to know when it changes via UI interaction. In WPF, I would just bind its SelectedItem using Mode=OneWayToSource, but Silverlight does not support that mode (afaik).
Treeview :
<controls:TreeView ItemsSource="{Binding Repository.MajorClasses}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" />
Is there a workaround that anyone has used? And anyone know why OneWayToSource is omitted from Silverlight?
It's really readonly, so you cann't do that. You can use TreeView as base control and create CustomTreeView with implementation of bindable SelectedItem. Or create own behavior(attached property). Or use some third party control (f.i. telerik).
If you just want your VM to be informed when the user changes the selection, you should be able to do exactly what you are doing (a two way binding).
I have this working in Visual studio so, I suggest trying it from there, might just be a problem with Blend. VS intellisense doesn't suggest SelectedItem when typing in the XAML editor but that doesn't stop it from working.
The bound property in your VM is definately of the right type (MajorClass by the looks of it)?
What you need to do is make use of an Interaction Trigger and bind it to the SelectedItemChangedevent as follows:
<sdk:TreeView x:Name="ModuleNavigationItemWrappersTreeView" ItemsSource="{Binding ModuleNavigationItemWrappers}">
<sdk:TreeView.ItemTemplate>
<sdk:HierarchicalDataTemplate ItemsSource="{Binding Children}">
<StackPanel Orientation="Horizontal" Margin="0,2,0,2">
<Image Source="/VanguardFinancials.Common;component/Images/icons/flag_blue.png" />
<TextBlock Margin="2,0,0,0" Text="{Binding ItemDescription}"></TextBlock>
</StackPanel>
</sdk:HierarchicalDataTemplate>
</sdk:TreeView.ItemTemplate>
<interactivity:Interaction.Triggers>
<interactivity:EventTrigger EventName="SelectedItemChanged">
<interactivity:InvokeCommandAction Command="{Binding TrackSelectedModuleNavigationItemWrapper}" CommandParameter="{Binding ElementName=ModuleNavigationItemWrappersTreeView}" />
</interactivity:EventTrigger>
</interactivity:Interaction.Triggers>
</sdk:TreeView>
Visit this for more information about Behaviors and Triggers. Hope this helps.

WPF ListBox ItemsSource with DataTemplate

I have a ListBox with an ItemsSource pointing to a static variable, and a DataTemplate for the ListBox's ItemTemplate that should be displaying the Description property of the variable the ItemsSource points to
<ListBox x:Name="classificationTypeListBox"
ItemsSource="{x:Static h:AmbientHighlightingStyleRegistry.Instance}"
SelectedIndex="0" Foreground="Black">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=(Description)}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I can put a break point on my application and view the ListBox. The ItemsSource does point to the variable I want and it looks like the ListBox is trying to display all the values because I can click and scroll down the it. However, no text is getting displayed so you can't actually tell what you're clicking. Also, while the break point is on, it says that the list box contains 0 items, maybe it should because I'm binding it, not sure. Any suggestions?
<TextBlock Text="{Binding Path=(Description)}" />
Why do you have parens in there? This syntax causes WPF to try to bind to an attached property, which is not what you want to do.

Correct way to do DataBinding in a WP7 UserControl

I'm building a Windows Phone 7 App. So, I'm using SilverLight 3(.7) and I'm having a bit of a problem with the UserControls that I've built. Here's how I'm doing it now:
UserControl has a DependencyProperty named Number
<UserControl x:Class="MyUserControl" x:Name="myUserControl">
<TextBlock Text="{Binding ElementName=myUserControl, Path=Number}"/>
</UserControl>
To use it I'm simply doing:
<MyUserControl Number="{Binding ElementName=MyPage, Path=SomeNumber}">
<MyUserControl Number="{Binding ElementName=MyPage, Path=SomeOtherNumber}">
This all works great, but if I add a name to one of the two instances of my control, things go wacky. For example:
<MyUserControl x:Name="SomeNumberControl"
Number="{Binding ElementName=MyPage, Path=SomeNumber}">
<MyUserControl Number="{Binding ElementName=MyPage, Path=SomeOtherNumber}">`
Then the data doesn't show up. It appears that the name given overrides the name specified in the UserControl and the bindings don't work.
So, I tried to do binding through the datacontext. And setting the DataContext to the UserControl.
so, my control became:
<UserControl x:Class="MyUserControl"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<TextBlock Text="{Binding Number}"/>
</UserControl>
With this nothing gets bound. It's like the datacontext is never set and even weirder when I put this control in another user control that I created, It appears that the parent control is now somehow bound to the MyUserControl instance.
So when I do the following:
<MyPage>
<MyUserControl Number={Binding SomeNumber}"/>
I get the error,
SomeNumber not found in type MyUserControl.
It's as if the binding for the parent control is now the instance of MyUserControl. Am I just doing something fundamentally wrong in how I'm doing bindings in my user control, or is this something strange with SilverLight 4 and WP7.
Any help on this is greatly appreciated.
If you have a DependecyProperty in your codebehind called Number you can set
DataContext = this;
That should allow you to bind directly to your Number property from TextBlock.
<TextBlock Text="{Binding Number}"/>

How can I change the visibility of elements inside a DataTemplate when a row is selected in a Silverlight datagrid?

I'm using the MVVM pattern. I've bound my items and I want to only show the edit button when a row is selected in the datagrid. It appears to be possible with triggers in WPF but we don't have triggers in Silverlight. I tried a TemplatedParent binding but I'm not sure what the TemplatedParent is in this case. We don't have RelativeSource ancestor in Silverlight either. At this point I'm going to look at a solution using the code behind...
<data:DataGrid.Columns>
<data:DataGridTemplateColumn IsReadOnly="True" Header="Name" Width="300">
<data:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Grid>
<TextBlock x:Name="textBlock" Text="{Binding Name, Mode=OneWay}" VerticalAlignment="Center" Margin="4,4,0,4"/>
<Button Margin="1,1,4,1" HorizontalAlignment="Right" VerticalAlignment="Center" Padding="7,4" Content="Edit" />
</Grid>
</DataTemplate>
</data:DataGridTemplateColumn.CellTemplate>
</data:DataGridTemplateColumn>
</data:DataGrid.Columns>
There are a couple ways you could do this in silverlight, although I don't think any of them can be pure XAML solutions. With MVVM, you then create property in your view model that you bind to the SelectedItem property of the DataGrid. From there, there are two differnt options:
If the individual items in the DataGird are themselves other view models, then you can give them a property like "IsEditable" and bind it to the visibility of the button. When the SelectedItem fo the parent ViewModel changes, go and update the IsEditable property of all the child viewmodels
If you dont have child view models, you can handle the loaded event of the Edit button. In the code behind, bind the visibility of the button to the selecteditem property in your view model, but also set up a binding converter that takes in the original bound item as a converter parameter. In the converter, you can check if the selected item is equal to the originally bound item
If only Silverlight had a RelativeSource FindAncestor binding...
One kind-of hacky idea I could suggest would be to put your editing controls into a RowDetailsTemplate on the DataGrid itself, then set the RowDetailsVisibilityMode to VisibleWhenSelected.
It might not be what you're after look-wise, but it probably "solves" your particular use-case.
If it doesn't, then I'd probably violate MVVM here (very carefully). Usually DataGrids are the bastard child edge case; they almost all need some variety of code-behind.

Resources