How can I create a silverlight combobox that drops down a treeview? - silverlight

I'm trying to create a user control that is a combobox that, when opened, presents a treeview of heirarchal data.
I created the user control and replaced a portion of the template in Popup with:
<ScrollViewer x:Name="ScrollViewer" BorderThickness="0" Padding="1">
<sdk:TreeView x:Name="Tree">
</sdk:TreeView>
</ScrollViewer>
However, I'm not sure how to enable binding on this. The treeview needs to be bound to a different datacontext than the combobox. I tried implementing a DependencyProperty on the user control that would allow me to set the datacontext, but I'm definitely not going about it the right way. At this point, all I get is an empty treeview.
Any help on this would be greatly appreciated.
P.S. One additional caveat is that I need to template the treeview like so:
<sdk:TreeView x:Name="Tree">
<sdk:TreeView.ItemTemplate>
<sdk:HierarchicalDataTemplate ItemsSource="{Binding ChildUnits}">
<StackPanel Orientation="Vertical" Width="200">
<TextBlock x:Name="name" TextWrapping="Wrap" Text="{Binding Name}" FontWeight="Bold" />
<TextBlock x:Name="type" Text="{Binding Id}" FontStyle="Italic" FontSize="10" Foreground="Gray" />
</StackPanel>
</sdk:HierarchicalDataTemplate>
</sdk:TreeView.ItemTemplate>
</sdk:TreeView>

Related

Silverlight textblock in a listbox not wrapping

I have a data bound Listbox as shown below. I want the textblock that holds the data to wrap. And I have not been able to.
What is the problem here?
Here is my code:
<DataTemplate x:Key="policyLbTemplate">
<StackPanel>
<TextBlock Text="{Binding name}" FontWeight="Bold"/>
<TextBlock Text="{Binding description}" TextWrapping="Wrap" />
</StackPanel>
</DataTemplate>
<ListBox VerticalAlignment="Stretch" HorizontalAlignment="Stretch" ItemsSource="{Binding Policies}"
ItemTemplate="{StaticResource policyLbTemplate}"
HorizontalContentAlignment="Stretch" />
You need to add one property to the list box: ScrollViewer.HorizontalScrollBarVisibility="Disabled", then the text will wrap (otherwise it grows offscreen). I have done it in the following code and it works fine for me.
<ListBox Name="lstbIcons" HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch"
VerticalAlignment="Stretch" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding UserActionName}" FontWeight="Bold"/>
<TextBlock Text="{Binding Description}" TextWrapping="Wrap" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
This is most likely because there is nothing restricting the width of the TextBlock so that it is growing offscreen. Do Horizontal scrollbars appear?
See the following related questions and try the solutions described:
WP7 TextBlock inside a ListBox not wrapping text
Force TextBlock to wrap in WPF ListBox
windows phone 7 TextBlock TextWrapping not honored in listbox
http://social.msdn.microsoft.com/forums/en-US/wpf/thread/37236ac6-05c3-4acc-baca-abc871ba64e0

How do I Raise an Event when the Binding is completed?

I have a TextBox in my application that i am developing and the binding is done in the xaml
I want to be able to raise an event when the binding of the TextBox Text Property is completed meaning when the text is loaded/changed through binding into the TextBox how do i achive this?
I tried TextChanged Event also Loaded Event but no luck right after the Binding is complected so how do i do it?
<ListBox x:Name="listBoxCategories" Background="Transparent" BorderThickness="0" Grid.Row="4" Grid.ColumnSpan="2" Margin="0" Padding="0" ItemContainerStyle="{StaticResource ListBoxItemStyle}" ItemsSource="{Binding ElementName=discussion_categoryDomainDataSource, Path=Data}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel x:Name="stackPanelCategory" Orientation="Vertical" Margin="0" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<TextBlock x:Name="TextBlockCategoryId" Text="{Binding Path=CategoryID}" />
<toolkit:Expander IsExpanded="True" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Style="{StaticResource ForumExpanderStyleRight}">
<toolkit:Expander.Header>
<TextBlock FontSize="16" FontWeight="Bold" Foreground="White" Margin="4,0,4,0" Text="{Binding CategoryName}" LayoutUpdated="TextBlock_LayoutUpdated" />
</toolkit:Expander.Header>
<ListBox x:Name="listBoxBoards" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Background="Transparent" BorderThickness="0" Margin="0" Padding="0" ItemContainerStyle="{StaticResource ListBoxItemStyle}" ItemsSource="{Binding CategoryBoards}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="0" HorizontalAlignment="Stretch" x:Name="GridBoard">
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</toolkit:Expander>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
at this line
<TextBlock x:Name="TextBlockCategoryId" Text="{Binding Path=CategoryID}" />
I want an event where when the Binding is completed i want to give a different data source for the list box under the parent stack panel so i need the binding event so when i have the catedory id int he text block which later will be hidden in the xaml ( which now is not collapsed for testing reasons )
This is a slightly peculiar thing to want to do, it might help if you tell us why you are wanting to do this?
However, with no other information to hand, I will propose a solution.
If the TextBox API events do not provide the infomation you need, try handing the LayoutUpdated event. This event fires each time layout occurs, which is typically as elements ae added to the visual tree. WHen this event fires inspect your TextBox.Text property to see if it is set.
This solved the problem for me :)
<TextBlock FontSize="16" FontWeight="Bold" Foreground="White" Margin="4,0,4,0" Text="{Binding CategoryName}" Loaded="TextBlock_Loaded" />
Loaded event in the inner Text block rather than the upper textblock because by the time this is loaded the upper text block's text is already bound so i can retrive the ID :)

WPF Nested Databinding; How Do I Bind To An Item Inside Another Item

I have a ListView bound to an ObservableCollection of CustomerContacts.
It works great so far, but being new to this, I'm not sure how to do the next part.
Each customer contact has several contact types, which I want to display under their name.
So inside of CustomerContacts I have another ObservableCollection of ContactTypes.
Here is my current datatemplate:
<DataTemplate x:Key="iconTemplate">
<DockPanel Height="133" Width="150">
<Image Source="/Tracks%203.5;component/Images/NoPic.png" Height="25" Width="25" Margin="1,0" />
<TextBlock DockPanel.Dock="Top" Text="{Binding FullName}" Margin="5,3,5,0" FontWeight="Bold" HorizontalAlignment="Left" />
<<TextBlock Text="{Binding Title}" Margin="5,0,5,3" HorizontalAlignment="Left" />>
</DockPanel>
</DataTemplate>
And here's my first attempt at putting the listview inside:
<DataTemplate x:Key="iconTemplate">
<DockPanel Height="133" Width="150">
<Image Source="/Tracks%203.5;component/Images/NoPic.png" Height="25" Width="25" Margin="1,0" />
<TextBlock DockPanel.Dock="Top" Text="{Binding FullName}" Margin="5,3,5,0" FontWeight="Bold" HorizontalAlignment="Left" />
<ListView ItemsSource="{Binding ContactTypes}">
<ListView.Template>
<ControlTemplate TargetType="ItemsControl">
<ItemsPresenter/>
</ControlTemplate>
</ListView.Template>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Margin="3,0,0,0" HorizontalAlignment="Center" Text="{Binding Path=ContactType}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<!--<TextBlock Text="{Binding Title}" Margin="5,0,5,3" HorizontalAlignment="Left" />-->
</DockPanel>
</DataTemplate>
I want to replace the TextBlock bound to Title with a ListView/ListBox/ItemsControl bound to the items in ContactTypes.
Somewhat similar to this question: < WPF: bind to a List inside a class > but without all the codebehind. It would be nice to have it in the XAML.
There's a couple things I would do here:
Simplify what you're trying to do in order to isolate the problem. Instead of that whole ListView business, just put in there an ItemsControl: <ItemsControl ItemsSource="{Binding ContactTypes}" /> That'll give you the default view of things, which may just show you the data type of your objects (whatever ContactTypes is), but it'll let you know if the binding is working. If it is, you'll get something listed there. If it isn't, you won't.
If you're not getting anything listed, go use Snoop to drill into it and look for errors. Snoop shows the databinding errors, allows you to inspect the DataContext of each of the items, etc.
If you're still having problems, it might benefit us if you posted your class definitions and your code where you wire things up. There might be some other underlying issues (for instance, is the ContactTypes property null when the binding initially occurs and you're not using INPC to let the binding system know when it changes?).

Silverlight 3 Datatemplate: Firing a button_click event

I have a datatemplate for a listbox stored in the ResourceDictionary. The template contains a button which when clicked should pass the listbox item to a seperate listbox
<DataTemplate x:Key="ListBoxContentPresenterTemplate">
<StackPanel Orientation="Horizontal">
<StackPanel Height="75" Width="100">
<TextBlock x:Name="Surname" Text="{Binding Property1}" FontFamily="Arial" FontSize="16" FontWeight="Bold" d:LayoutOverrides="Width"/>
<TextBlock x:Name="Firstname" Text="{Binding Property2}" Foreground="#FFC9C23E" FontFamily="Arial" FontSize="12" d:LayoutOverrides="Width"/>
</StackPanel>
<Button x:Name="Button1" Content="Press" />
</StackPanel>
</DataTemplate>
I don't know how to fire the event as adding it in the xaml as I normally would doesn't work here(presumably as it's a template).
Any help would be much appreicated.
DataTemplate is not the problem to subscribe to events. May be only if your DataTemplate is located in a separate resources file, so you have no rational place to place the event handler. If so you can make use of Commands (I believe this will work in version 3 too).

Tab order and index in WPF using the MVVM pattern

I'm having an issue with tabbing through the controls on a WPF application using the MVVM pattern. I have the following XAML which defines a tree structure
<Grid Background="Transparent" Margin="10">
<TreeView ItemsSource="{Binding FirstLevelNavigableViewModels}" Background="Transparent"
HorizontalContentAlignment="Stretch"
HorizontalAlignment="Stretch"
BorderThickness="0"
ItemContainerStyle="{StaticResource TreeViewItemStyle1}">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type ViewModel:VendorViewModel}" ItemsSource="{Binding Children}">
<View:VendorView HorizontalContentAlignment="Stretch" />
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type ViewModel:ProductViewModel}">
<View:ProductView HorizontalContentAlignment="Stretch" />
</DataTemplate>
</TreeView.Resources>
</TreeView>
</Grid>
When the treeview is loaded, the XAML for the "ProductView" is as follows
<Border Margin="0,2,2,2" CornerRadius="3" Background="#3FC7B299" DockPanel.Dock="Right" HorizontalAlignment="Right" Width="109">
<StackPanel Orientation="Vertical" Margin="6,4">
<DockPanel>
<TextBlock DockPanel.Dock="Left" FontFamily="Segoe" FontSize="10" FontWeight="Medium"
Foreground="Black" Opacity="0.75"
Text="CALC. REG. PRICE"></TextBlock>
<Button Width="10" Height="10" Background="Transparent" BorderBrush="Transparent" BorderThickness="0" Padding="-4" Margin="0" Command="{Binding UserDefinedRetailPriceCommand}" Visibility="{Binding UserDefinedRetailPriceButtonView}">
<Image Width="10" Height="10" Source="/Arhaus.Pricing.Client;component/Styles/Images/error.png"></Image>
</Button>
</DockPanel>
<TextBox FontFamily="Segoe" FontSize="16" FontWeight="Medium" KeyboardNavigation.IsTabStop="True" KeyboardNavigation.TabIndex="{Binding RegularPriceTabIndex}"
Foreground="Black" Opacity="0.9" KeyboardNavigation.TabNavigation="Continue"
ebf:LostFocusBehaviour.LostFocusCommand = "{Binding LostFocusSugg}"
Text="{Binding NewSuggestedRetailPrice,Converter={StaticResource FormattingConverter}, ConverterParameter=' \{0:C\}', Mode=TwoWay, UpdateSourceTrigger=LostFocus}" Background="#FFE6DED3" BorderBrush="#FFE6DED3" DataContext="{Binding StringFormat=\{0:c\}, NotifyOnValidationError=True}" Padding="0" TabIndex="1"></TextBox>
</StackPanel>
</Border>
I have the Tab Index bound to an integer that is ever increasing and bound as the treeview is loaded (I.E. I have it setup as tab index 1, 2, 3 etc. as each successive model is loaded).
I would like to be able to hit tab and jump to the next textbox in the treeview but when I click the TAB key, nothing happens. I'm not sure if I have the tabbing setup correctly but I'm very new to WPF and at a loss as to where and how to set the tabbing to make it work. I'm used to WinForms where you just set the tab index and go from there.
Thank you for your assistance, I apologize for the large code block.
I don't have a solution ready but some thoughts that maybe may help:
I don't know what RegularPriceTabIndex returns but probably it begins for each new TreeViewItem at the same index?
The same tab-index is given then multiple times because of repeating use of ProductView. Perhaps this leads to a problem. You can try setting FocusManager.IsFocusScope="true" for the ProductView. Maybe this helps.
Try also to set Control.IsTabStop="true" on the TextBox.

Resources