Windows Phone 7 Silverlight DataTemplate HyperlinkButton content - silverlight

I'm trying to make a list that is populated by external data and I have a datatemplate for it.
Each element of the list is composed of an image and two textblocks, and is linked to a specific page.
I'm trying to do this but when I wrap the structure with an HyperlinkButton, I just get a blank page.
I don't know if I'm doing something stupid wrong or it's not possible to have so many items in an HyperlinkButton. If it's not possible to do it this way, can someone guide me to the best solution to do this? Here's the code:
<Grid x:Name="ContentPanel" Margin="0,140,0,0" Background="White">
<ListBox HorizontalAlignment="Stretch" Name="itemList" VerticalContentAlignment="Stretch">
<ListBox.ItemTemplate>
<DataTemplate>
<HyperlinkButton>
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" MinWidth="480">
<Grid.Background>
<ImageBrush ImageSource="/app;component/Images/degradat_cela.png" Stretch="UniformToFill" AlignmentY="Top" AlignmentX="Left" />
</Grid.Background>
<Grid.RowDefinitions>
<RowDefinition Height="35" />
<RowDefinition Height="35" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50" />
<ColumnDefinition Width="430*" />
</Grid.ColumnDefinitions>
<Border HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Height="38" Width="38" Grid.RowSpan="2" Grid.Column="0" Grid.Row="0" BorderThickness="1" BorderBrush="#FFFF003F" Padding="1">
<Image HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Name="listImage" Width="36" Height="36" Source="{Binding image}" />
</Border>
<TextBlock Margin="5 12 0 0" Grid.Column="1" Grid.Row="0" Name="title" Foreground="Black" Text="{Binding title}" FontWeight="Bold" FontSize="18" />
<TextBlock Margin="5 0 0 8" Grid.Column="1" Grid.Row="1" Name="description" Foreground="Black" Text="{Binding subtitle}" FontSize="14" />
</Grid>
</HyperlinkButton>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
I will also accept any suggestions to make my code better, as I'm new to .NET and I probably don't do things the best way!

Remove the HyperlinkButton and instead use the SelectionChanged event of the ListBox. So add this property to your ListBox:
SelectionChanged="myListBox_SelectionChanged"
Then in your code behind do this:
private void myListBox_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
if ((sender as ListBox).SelectedIndex == -1)
return;
NavigationService.Navigate(new System.Uri(string.Format("/Drilldown.xaml?Index={0}",(sender as ListBox).SelectedIndex),System.UriKind.Relative));
}
This code assumes a drilldown page that uses a query string to change it's layout. This is just for example. If instead of index you wanted to reference some property of the bound item you could instead do something like this (assuming an ID property):
int itemID = ((sender as ListBox).SelectedItem as MyApp.Model.myItem).ID;
NavigationService.Navigate(new System.Uri(string.Format("/Drilldown.xaml?ID={0}",itemID),System.UriKind.Relative));

Related

WPF Canvas Mouse Events have disappeared [duplicate]

I am currently fighting against another WPF struggle, namely mouse events.
I basically have a very simple control (a Border containing a Grid which itself has a few TextBlocks). I am trying to achieve a simple behavior: Double click should turn the control into edit mode (which in fact hides the TextBlocks with TextBoxes bound to the same data.
Nothing fancy, right? Well still, I'm struggling. The MouseDoubleClick linked to my UserControl just fires when I click in a control (like, clicking ON a TextBlock). If I click on an empty space between TextBlocks, nothing is fired. Not even MouseDown.
How could I make it work so as to catch every mouse click? I assumed that linking a MouseDown event to a Border should catch every click on the border but... it ended up not catching clicks on empty parts of the border.
Here is some draft code I made for you to run it:
XAML:
<StackPanel Orientation="Vertical">
<Border Height="400" Width="400" HorizontalAlignment="Center" VerticalAlignment="Center" BorderBrush="Black" BorderThickness="2"
MouseDown="Border_MouseDown" MouseUp="Border_mouseUp">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Text="BLUFF" Grid.Column="0" Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBlock Text="BLUFF" Grid.Column="0" Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBlock Text="BLUFF" Grid.Column="0" Grid.Row="2" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBlock Text="BLUFF" Grid.Column="1" Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBlock Text="BLUFF" Grid.Column="1" Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBlock Text="BLUFF" Grid.Column="1" Grid.Row="2" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBlock Text="BLUFF" Grid.Column="2" Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBlock Text="BLUFF" Grid.Column="2" Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBlock Text="BLUFF" Grid.Column="2" Grid.Row="2" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</Border>
<TextBlock Height="100" Width="300" HorizontalAlignment="Center" TextAlignment="Center" x:Name="thetext" Visibility="Collapsed"
Foreground="White" Background="Red" Text="CLICKED!" />
</StackPanel>
Code behind:
private void Border_MouseDown(object sender, MouseButtonEventArgs e)
{
thetext.Visibility = Visibility.Visible;
}
private void Border_mouseUp(object sender, MouseButtonEventArgs e)
{
thetext.Visibility = Visibility.Collapsed;
}
Now try to click one of the "BLUFF" texts: A "CLICKED" Text will appear. Try clicking somewhere else, between the TextBlocks: Nothing happens.
Thank you!
<StackPanel Background="Transparent" ... >
or
<Border Background="Transparent" ... >
should do the trick...
This makes the grid transparent, however visible for mouse-clicks.
Look here form more Information.
There are some other circumstances, where you have to use the PreviewXXX- event, this is when a child element "swallows" the event away, but in your case, the above should be what you're looking for.

Bind to single object in viewmodel

I got this property in my viewmodel:
private PushPinModel selectedPushPinModel;
public PushPinModel SelectedPushPinModel
{
get { return selectedPushPinModel; }
set
{
selectedPushPinModel = value;
RaisePropertyChanged(() => SelectedPushPinModel);
}
}
And I want to bind the view to show which one is selected:
<ContentControl DataContext="{Binding SelectedPushPinModel}" VerticalAlignment="Top">
<ContentControl.ContentTemplate>
<DataTemplate>
<Grid Height="100" VerticalAlignment="Top">
<Grid.RowDefinitions>
<RowDefinition Height="20*"/>
<RowDefinition Height="38*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="91*"/>
<ColumnDefinition Width="389*"/>
</Grid.ColumnDefinitions>
<Border Opacity="0.95" Width="480" Padding="0,0,0,0" BorderThickness="0" HorizontalAlignment="Left" BorderBrush="Transparent" Background="White" Grid.ColumnSpan="2" Grid.RowSpan="2"/>
<Image Width="70" Height="70" HorizontalAlignment="Center" VerticalAlignment="Center" Source="{Binding Icon}" Grid.Column="0" Grid.Row="0" Grid.RowSpan="2" />
<TextBlock Text="{Binding Header}" Grid.Column="1" Grid.Row="0" Style="{StaticResource TextboxLabelStyle}"/>
<TextBlock Text="{Binding Body}" Grid.Column="1" Grid.Row="1" Style="{StaticResource DefaultTextBlockStyle}"/>
</Grid>
</DataTemplate>
</ContentControl.ContentTemplate>
</ContentControl >
However I can't get it to work. The bindings is not showing in the view and I'm not getting any binding errors. Is it the correct way to bind to a single object?
I much rather having it like this instead of binding directly with {Binding SelectedPushPinModel.Body} which more dirty.
Any suggestions how to accomplish this?
Thanks
Try this:
<Label Content="{Binding SelectedPushPinModel}" />
See what that gives you (if anything). Also, check the 'output' window for errors.
This line:
<ContentControl DataContext="{Binding SelectedPushPinModel}">
will only work if the DataContext for the ViewModel (Class) has been properly bound higher on the page. If it isn't then the Label binding provided above will show blank.
Solved it, replaced DataContext on the ContentControl with Content
<ContentControl Content="{Binding SelectedPushPinModel}" VerticalAlignment="Top">
Thanks to sircodesalot for pointing me to the right direction!

WPF Modal Window Transparency

I have created a modal WPF window that looks as follows:
Here is the code for the window:
<Window x:Class="Dionysus.Core.Controls.ModalWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ModalWindow" AllowsTransparency="True" Background="Transparent" WindowStyle="None">
<Grid Name="MainGrid">
<Rectangle Fill="Gray" Opacity="0.7" />
</Grid>
The "ErrorControl" is then added as follows:
MainGrid.Children.Add(uc);
The problem is as soon as I expand the stack trace, the controls transparency also changes:
I am assuming this has something to do with the ScrollViewer that uses the incorrect transparency, ie of the Rectangle instead of the containing Window.
I have also set the Opacity of the UserControl which owns the ScrollViewer to 1 and then binded the Opacity:
<ScrollViewer Background="WhiteSmoke" Opacity="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}, Path=Opacity}">
Can anyone help me?
--
UPDATE
Here is the code for the UserControl that is inserted into the Window
<Grid x:Name="LayoutRootx" Background="WhiteSmoke">
<StackPanel VerticalAlignment="Stretch">
<TextBlock TextWrapping="Wrap" Margin="5" Text="An error has occured:" Foreground="Black" FontSize="15" FontWeight="Medium"/>
<TextBlock TextWrapping="Wrap" Margin="5,10,5,5" Text="{Binding Error}"/>
<odc:OdcExpander Header="Stack Trace" Margin="5" IsExpanded="False" Background="WhiteSmoke">
<TextBox Text="{Binding StackTrace}" TextWrapping="Wrap" Margin="5,10,5,5" IsReadOnly="True" MaxHeight="370"/>
</odc:OdcExpander>
<odc:OdcExpander Header="Comment" Margin="5" IsExpanded="False">
<TextBox Text="{Binding Comment}" TextWrapping="Wrap" Margin="5,10,5,5" MaxHeight="370" Name="txtComment"/>
</odc:OdcExpander>
<StackPanel Margin="5,10,5,5" Orientation="Horizontal" HorizontalAlignment="Left">
<Button Style="{StaticResource DionysusButton}" Width="100" Height="23" IsDefault="True" Name="btnSendError">
<StackPanel Orientation="Horizontal">
<Image Source="/Dionysus.Shell;component/Images/camera-icon.png" Margin="0,0,5,0">
</Image>
<TextBlock Text="Send to IT" VerticalAlignment="Center"/>
<core:DionysusTriggerAction Height="0" Width="0" TargetControl="{Binding ElementName=btnSendError}" MethodName="SendError"></core:DionysusTriggerAction>
</StackPanel>
</Button>
<Button Style="{StaticResource DionysusButton}" Width="100" Height="23" Name="btnExit" Margin="10,0,0,0" IsCancel="True">
<StackPanel Orientation="Horizontal">
<Image Source="/Dionysus.Shell;component/Images/DeleteRed.png" Margin="0,0,5,0">
</Image>
<TextBlock Text="Close" VerticalAlignment="Center"/>
</StackPanel>
</Button>
<core:DionysusTriggerAction Height="0" Name="triggerAction2" Width="0" TargetControl="{Binding ElementName=btnExit}" MethodName="Exit"></core:DionysusTriggerAction>
</StackPanel>
</StackPanel>
</Grid>
If your window has a fixed size and cannot be resized, you can use the following trick:
<Grid>
<Border BorderThickness="100" BorderBrush="Gray" Opacity="0.7">
<Grid Background="White" Grid.Column="1" Grid.Row="1" x:Name="contentPlaceHolder">
<TextBlock Text="HELLO WORLD" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</Border>
</Grid>
However, it is unlikely that your Window will always have the same size, so to make it more dynamic, you could change the layout of the Window as follows:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="YourDesiredSize"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="YourDesiredSize"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Rectangle Fill="Gray" Opacity="0.7" Grid.Row="0" Grid.ColumnSpan="3"/>
<Rectangle Fill="Gray" Opacity="0.7" Grid.Row="2" Grid.ColumnSpan="3"/>
<Rectangle Fill="Gray" Opacity="0.7" Grid.Row="1" Grid.Column="0"/>
<Rectangle Fill="Gray" Opacity="0.7" Grid.Row="1" Grid.Column="2"/>
<Grid Grid.Column="1" Grid.Row="1" Background="White" x:Name="contentPlaceHolder">
<TextBlock Text="HELLO WORLD" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</Grid>
The result of this window placed on top of another looks more or less like this:
and then instead of adding to the MainGrid, add the UserControl to the contentPlaceHolder or however you want to call it:
contentPlaceHolder.Children.Add(uc);
Okay so I found a solution that works for me, I'm sure it's not the best but it might help someone having the same problem as I did.
The problem was that controls within my UserControl that I added to my Window were transparent, although I could not figure out the reason, I found a simple workaround.
By changing the OpacityMask property of the UserControl to whatever the required Background colour is, even if the controls opacity changes, it will be masked with the Brush that you supply.
uc.OpacityMask = Brushes.WhiteSmoke;
Hope it helps someone!

Making a WPF TextBox be only as wide as the room it has but expand when the space expands?

Notice how the textbox expands to the right until it has enough horizontal space to fit the content? Well I'd like it to not expand and fit the text with the space it has in the window.
If the windows expands, then the Grid.Column it's in will expand, but the textbox itself should expand to fit. Simple enough?
Any suggestions? This is my first foray into WPF and so far it's been pretty sleek.
Edit: Here's my XAML markup:
<Window x:Class="GameLenseWpf.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="450" Width="350" MinHeight="450" MinWidth="350">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="0.15*" />
<RowDefinition />
</Grid.RowDefinitions>
<Image Grid.Row="0" Stretch="Fill" Source="Image/topBarBg.png" />
<StackPanel Orientation="Horizontal" Grid.Row="0">
<TextBlock Text="Platform"
Foreground="White"
FontFamily="Georgia"
FontSize="15"
Margin="10"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
<ComboBox x:Name="cmbPlatform"
Margin="10"
FontFamily="Georgia"
FontSize="15"
MinHeight="30"
MinWidth="140"
VerticalAlignment="Center"
VerticalContentAlignment="Center" SelectionChanged="cmbPlatform_SelectionChanged">
<ComboBoxItem>All Platforms</ComboBoxItem>
<ComboBoxItem>Playstation 3</ComboBoxItem>
<ComboBoxItem>XBox 360</ComboBoxItem>
<ComboBoxItem>Wii</ComboBoxItem>
<ComboBoxItem>PSP</ComboBoxItem>
<ComboBoxItem>DS</ComboBoxItem>
</ComboBox>
</StackPanel>
<Image x:Name="imgAbout" Grid.Row="0" Source="Image/about.png"
Height="16" HorizontalAlignment="Right"
VerticalAlignment="Center"
Margin="0 0 10 0" />
<ListBox Grid.Row="1" x:Name="lstGames" Background="#343434" Padding="5">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Height="120" Margin="0 10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="90"/>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
</Grid.RowDefinitions>
<Border BorderBrush="#202020" BorderThickness="5" CornerRadius="4" Panel.ZIndex="0">
<Image Grid.Row="0" Grid.Column="0" Source="{Binding ImageUrl}" Stretch="Fill"/>
</Border>
<StackPanel Grid.Row="0" Grid.Column="1" Margin="12 0 0 0">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Title:" FontFamily="Arial" Foreground="White"/>
<TextBlock Text="{Binding Title}" FontFamily="Arial" Foreground="White" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Release Date:" FontFamily="Arial" Foreground="White" />
<TextBlock Text="{Binding ReleaseDate}" FontFamily="Arial" Foreground="White" />
</StackPanel>
<TextBlock Text="Synopsis" FontFamily="Arial" Foreground="White" />
<TextBox Background="#454545" Text="{Binding Synopsis}" MinHeight="76" />
</StackPanel>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Window>
To get a TextBox to wrap inside a ListBox you can make the following changes:
Set the content of the listbox equal to the width of the listbox using: HorizontalContentAlignment="Stretch".
Disable the horizontal scrollbar of the listbox to prevent listbox from getting the desired size of the controls and preventing the word wrap in your textbox.
Set TextWrapping="Wrap" in the TextBox
Here is the XAML:
<ListBox Grid.Row="1" x:Name="lstGames" Background="#343434" Padding="5"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
HorizontalContentAlignment="Stretch" >
</ListBox>
<TextBox Text="{Binding Synopsis}" MinHeight="76" TextWrapping="Wrap" />
I believe you need to set the Margin property of your textbox control. In the designer, you can see little circles around each textbox (and each control when you focus them, for that matter). Click the little circle on the right side of the textbox, to make that control grow marginally with the available space in the current layout control (by clicking the circle, the margin will be added into the XAML).
I don't know if in your image you've already adjusted the window size, but with that image it appears you'll also need to set the width for your textbox.
Does this help?

Wpf Bind View to ViewModel add to wpf window

I have a view that contains a ItemsControl with some textblocks inside to display the name and other information. in my window I am adding the view to the window as follows and in the code behind of the window i am binding the datacontext of the view to the view model in the MainWindow Loaded event as follows ViewOwnerSideBar.DataContext = viewModel The application compiles but when I run it I dont get data? I checked my viewmodel and I do have data in my collection that I am returning. Does anyone have any good examples of how to do this. I am going to have a sidebar view and a main view on the right displaying the details of the owner.
This is my View
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Resources/ColorsAndBrushes.xaml"/>
<ResourceDictionary Source="/Resources/DefaultStyles.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<DockPanel >
<ScrollViewer VerticalScrollBarVisibility="Auto" >
<ItemsControl Width="250"
VerticalAlignment="Stretch"
BorderThickness="0"
ItemsSource="{Binding Path=AllOwners}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Margin="2">
<Border Margin="2 2 0 0"
CornerRadius="4"
Background="Gray"
Opacity=".5" />
<Border BorderBrush="{StaticResource redBrush}"
BorderThickness="2"
CornerRadius="4"
Background="White"
Margin="0 0 2 2"
Padding="3">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Grid.ColumnSpan="2"
FontWeight="Bold"
Text="{Binding FullName}" />
<TextBlock Grid.Row="1"
Text=" FirstName: " />
<TextBlock Grid.Row="1"
Grid.Column="1"
Text="{Binding FirstName}" />
<TextBlock Grid.Row="2"
Text=" Email: " />
<TextBlock Grid.Row="2"
Grid.Column="1"
Text="{Binding Email}" />
</Grid>
</Border>
<Button Style="{StaticResource openButton}" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</DockPanel>
This is my window
<DockPanel>
<v:HeaderTopBar DockPanel.Dock="Top"></v:HeaderTopBar>
<!--<uc:SearchBar DockPanel.Dock="Top" />-->
<StatusBar DockPanel.Dock="Bottom">
<StatusBarItem DockPanel.Dock="Right">
<Slider x:Name="zoomSlider"
Width="125"
Value="1"
Minimum=".5"
Maximum="2" />
</StatusBarItem>
<StatusBarItem DockPanel.Dock="Right">
<TextBlock>Zoom:</TextBlock>
</StatusBarItem>
<StatusBarItem>
<TextBlock Text="{Binding StatusText}" />
</StatusBarItem>
</StatusBar>
<Expander DockPanel.Dock="Left"
ExpandDirection="Right"
IsExpanded="True"
BorderThickness="0 1 1 1"
BorderBrush="Gray"
Margin="0 2 0 0"
Padding="2">
<Expander.Header>
<TextBlock Text="Contacts"
FontSize="14"
FontWeight="Bold">
<TextBlock.LayoutTransform>
<RotateTransform Angle="90" />
</TextBlock.LayoutTransform>
</TextBlock>
</Expander.Header>
<v:OwnerSideBar/>
</Expander>
<TabControl x:Name="tabs"
Grid.Column="2"
Margin="5 0">
<TabControl.LayoutTransform>
<ScaleTransform ScaleX="{Binding ElementName=zoomSlider,
Path=Value}"
ScaleY="{Binding ElementName=zoomSlider,
Path=Value}" />
</TabControl.LayoutTransform>
</TabControl>
</DockPanel>
Firstly, ensure that the AllOwners collection you are binding to is an ObservableCollection.
Also, check the Output window in Visual Studio when executing, look for First chance exceptions being caught. This will be a clue as to where your binding problem will be.
I like to put a textblock on the View bound to the Items.Count property on the ItemsControl so that you can see if it is binding and not rendering anything or not binding correctly.
Give the ItemsControl a name, then put a textblock in:
<TextBlock Text="{Binding ElementName=itemControl1,Path=Items.Count}/>
This might be something you already looked at, but you might have a binding typo, did you check your output window to see if you get any trace messages?
And I guess I'm blind but I don't see where your usercontrol is in the xaml of the second entry.

Resources