I have been trying to have a popup whenever I press a button.
However. Lets say that I have a lot of text on that popup and then it can go over the application window bounds.
How I can I tell the popup to keep within the application window bounds in xaml code?
It would be great with some examples in xaml code on how to tell the Popup element to keep within the application
Thanks
Xaml code:
...
<ToggleButton Grid.Row="1" Grid.Column="1" Margin="0,4"
x:Name="Somethingname"
Height="30"
Template="{StaticResource ComboBoxToggleButton}"
Content="Hello man"/>
<Popup Grid.Row="1" Grid.Column="1" x:Name="PopupMe"
Style="{StaticResource PopupStyle}"
ClipToBounds="True">
<TreeView ItemsSource="{Binding SomeObservableCollection}"
Width="{Binding ElementName=DetaljerHjemmmelToggler, Path=ActualWidth}"
ItemTemplate="{StaticResource SomeTemplate}"
cal:Message.Attach="[Event SelectedItemChanged] = [Action TreeView_SelectedItem($this, $source)]">
</TreeView>
</Popup>
...
In ResourceDictionary XAML file:
<HierarchicalDataTemplate x:Key="SomeTemplate" ItemsSource="{Binding ChildrenCollection}">
<TextBlock Text="{Binding Path=TekstBlaaah}" Style="{StaticResource Label}"/>
</HierarchicalDataTemplate>
<Style TargetType="{x:Type Popup}" x:Key="PopupStyle">
<Setter Property="IsOpen" Value="{Binding ElementName=Somethingname, Path=IsChecked}"/>
<Setter Property="AllowsTransparency" Value="True"/>
<Setter Property="PlacementTarget" Value="{Binding ElementName=Somethingname}"/>
<Setter Property="PopupAnimation" Value="Slide"/>
<Setter Property="StaysOpen" Value="False" />
<Setter Property="Placement" Value="Bottom"/>
</Style>
Check it out:
Custom popup and windows in WPF the MVVM way
Sample is also available
Related
I have a textbox/combobox displaying a particular path and both the textbox and combobox are already set to change size according to their contents. If the path is very long, it goes beyond the window screen and the "browse button" I have given gets hidden.(refer image for clarity).Note:I have this problem for both text & comboboxes.
Here's the snippet of a particular case:
<Label Content="_Layout Report Output Path:" Grid.Row="5" Target="{Binding ElementName=TxtLytRepPath}"/>
<StackPanel Grid.Row="5" Grid.Column="1" Orientation="Horizontal">
<ComboBox Name="CmbLytRepPath" Grid.Column="1" Text="{Binding LayoutReportPath, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" IsEditable="True" IsReadOnly="True"/>
<Button Name="BtnLytRepPath" Style="{StaticResource BrowseButton}"/>
</StackPanel>
</Label>
Button Style:
<Style TargetType="Button" x:Key="BrowseButton">
<Setter Property="Content" Value="..."/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="Margin" Value="2"/>
<Setter Property="MinHeight" Value="23"/>
<Setter Property="Width" Value="40"/>
</Style>
I cannot use a wrap panel as its makes the UI bad.Please suggest me some solution.
In your example, you close twice the label.
I think you will try with a dockpanel
<DockPanel Grid.Row="5" Height="??? if need">
<Label DockPanel.Dock="Left" Content="_xxx"/>
<Button DockPanel.Dock="Right" Style=” ”/>
<ComboBox />
</DockPanel>
Regards
I have a chunk of xaml that duplicates the same pattern six times and would like to reduce that footprint by eliminating the duplication. I'm running into one snag that I need help with.
Background: I have a class that instantiates another class six times (phases of a project as you will).
public ECN(string ecnNumber) {
_ECNNumber = ecnNumber;
//instantiate each phase to be populated or not
_PurchaseParts = new ECNPhase();
_PieceParts = new ECNPhase();
_Weldments = new ECNPhase();
_BOMCfg = new ECNPhase();
_Cleanup = new ECNPhase();
_PRAF = new ECNPhase();
}
Inside each phase is a collection of Changes (another class) referenced in the ECNPhase Class. Each phase has data that is unique to each phase that is shown in a unique view, this is where my snag is which I will show later.
Example of the duplicate xaml Code with the main difference being the different view inside each expander:
<StackPanel Margin="0">
<!--Section for Purchase parts-->
<StackPanel Orientation="Horizontal" >
<CheckBox Margin="0,5,5,5" IsChecked="{Binding Path=MyWorkspace.CurrentSelectedItem.PurchaseParts.HasPhase,Mode=TwoWay}"/>
<StackPanel Orientation="Horizontal">
<StackPanel.Style>
<Style TargetType="{x:Type StackPanel}">
<Setter Property="IsEnabled" Value="False"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=MyWorkspace.CurrentSelectedItem.PurchaseParts.HasPhase}" Value="True">
<Setter Property="IsEnabled" Value="True"/>
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
<Expander Header="Purchase Parts" Margin="0,0,10,0" Width="110">
<view:PurchasePartsView/>
</Expander>
<CheckBox Content="Submit" Margin="10,5,0,5"/> <!--add a command to handle the submit checkbox event-->
<Label Content="Status:" Margin="10,0,0,0" HorizontalContentAlignment="Right" Width="60"/>
<Label Content="{Binding Path=MyWorkspace.CurrentSelectedItem.PurchaseParts.Status}"/>
</StackPanel>
</StackPanel>
<!--Section for Piece Parts-->
<StackPanel Orientation="Horizontal">
<CheckBox Margin="0,5,5,5" IsChecked="{Binding Path=MyWorkspace.CurrentSelectedItem.PieceParts.HasPhase,Mode=TwoWay}"/>
<StackPanel Orientation="Horizontal">
<StackPanel.Style>
<Style TargetType="{x:Type StackPanel}">
<Setter Property="IsEnabled" Value="False"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=MyWorkspace.CurrentSelectedItem.PieceParts.HasPhase}" Value="True">
<Setter Property="IsEnabled" Value="True"/>
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
<Expander Header="Piece Parts" Margin="0,0,10,0" Width="110">
<view:PiecePartsView/>
</Expander>
<CheckBox Content="Submit" Margin="10,5,0,5"/> <!--add a command to handle the submit checkbox event-->
<Label Content="Status:" Margin="10,0,0,0" HorizontalContentAlignment="Right" Width="60"/>
<Label Content="{Binding Path=MyWorkspace.CurrentSelectedItem.PieceParts.Status}"/>
</StackPanel>
</StackPanel>
<!--duplicated four more times-->
</StackPanel>
What I'd like to do is:
<StackPanel>
<view:PhaseView DataContext="{Binding Path=MyWorkspace.CurrentSelectedItem.PurchaseParts}"/>
<view:PhaseView DataContext="{Binding Path=MyWorkspace.CurrentSelectedItem.PieceParts}"/>
<!--four more phases-->
</StackPanel>
Where the PhaseView will be the template that handles the duplication and this is where I'm hitting a snag. Each phase needs a unique view (userControl) selected based off of the datacontext of the PhaseView.
<StackPanel Orientation="Horizontal" >
<CheckBox Margin="0,5,5,5" IsChecked="{Binding Path=HasPhase,Mode=TwoWay}"/>
<StackPanel Orientation="Horizontal">
<StackPanel.Style>
<Style TargetType="{x:Type StackPanel}">
<Setter Property="IsEnabled" Value="False"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=HasPhase}" Value="True">
<Setter Property="IsEnabled" Value="True"/>
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
<Expander Header="DisplayName" Margin="0,0,10,0" Width="110">
<!--add somthing here to select the correct view based on the datacontext-->
<!--<local:PurchasePartsView/> This user control adds a datagrid that is unique to each phase-->
</Expander>
<CheckBox Content="Submit" Margin="10,5,0,5"/> <!--add a command to handle the submit checkbox event-->
<Label Content="Status:" Margin="10,0,0,0" HorizontalContentAlignment="Right" Width="60"/>
<Label Content="{Binding Path=Status}"/>
</StackPanel>
</StackPanel>
I was thinking of using a datatrigger somehow lik shown below, but I haven't had any luck figuring it out. I know there's got to be a way to do this, and it's probably something simple and dumb. Any help would be much appreciated.
<DataTrigger Binding="{Binding Path=DisplayName}" Value="Purchase Parts">
<Setter Property="DataContext" Value="{Binding }"/> <!--Don't know how to bind the DataContext-->
</DataTrigger>
Thanks,
Ok, thanks to Bradley I looked into the DataTemplateSelector and this is what I came up with.
In my UserControl resources I set up several DataTemplates and a reference to the TemplateSelector class that overides the DataTemplateSelector class.
XAML Resources:
<UserControl.Resources>
<local:TemplateSelector x:Key="myTemplateSelector"/>
<DataTemplate x:Key="PurchasePartsTemplate">
<view:PurchasePartsView/>
</DataTemplate>
<DataTemplate x:Key="PiecePartsTemplate">
<view:PiecePartsView/>
</DataTemplate>
<!--Four more templates-->
</UserControl.Resources>
Code Behind for DataTemplateSelector override. Note: I couldn't figure out a way to bind to the ECNPhase class so I bound to the DisplayName property in my class to pull out the correct instance being represented.
class TemplateSelector : DataTemplateSelector {
public override DataTemplate SelectTemplate(object item, DependencyObject container) {
FrameworkElement element = container as FrameworkElement;
if(element != null && item != null && item is string) {
string phase = (string)item;
if(phase == "Purchase Parts") {
return element.FindResource("PurchasePartsTemplate") as DataTemplate;
}else if(phase == "Piece Parts") {
return element.FindResource("PiecePartsTemplate") as DataTemplate;
}
}
return null;
}
}
I'm calling this class in my UserContol like this:
<Expander Header="{Binding Path=DisplayName}" Margin="0,0,10,0" Content="{Binding Path=DisplayName}"
ContentTemplateSelector="{StaticResource myTemplateSelector}"/>
There isn't an items control associated with the expander so I used the content control. I pass the DisplayName into the control property and the contentTemplateSelector uses the myTemplateSelector resource which goes into the codebehind and selects the appropriate datatemplate to use based on the DisplayName.
Now I can call my reusable template like so:
<StackPanel Margin="0">
<view:ChangePhaseView DataContext="{Binding Path=MyWorkspace.CurrentSelectedItem.PurchaseParts}"/>
<view:ChangePhaseView DataContext="{Binding Path=MyWorkspace.CurrentSelectedItem.PieceParts}"/>
</StackPanel>
#Bradley, thank you for pointing me in the right direction.
I am trying to show one collapsed stackpanel on button click, but I'm having problems so I tried reverse my thoughts and I was able to collapse an visible stackpanel. But unfortunately I was unable to implement the behavior I want, show an collapsed stack panel on button click. To the code :D
XAML
<Button x:Name="sentButton" Content="Add Friend" Style="{DynamicResource FlatButtonStyle}" Margin="493,0,0,0" HorizontalAlignment="Left" Width="106"/>
<StackPanel Style="{DynamicResource stackCollapsed}" Visibility="Collapsed">
<Label Content="Invite Friends" FontWeight="Bold" Margin="0,0,477,0" Height="32" />
<StackPanel Orientation="Horizontal" Margin="26,0,0,0">
<Label Content="Enter your friend's email" Width="222" Height="25" />
<TextBox Text="{Binding Email, UpdateSourceTrigger=PropertyChanged}" Style="{DynamicResource MyTextBox}" x:Name="textBoxEmail" Width="298"/>
<Button x:Name="button1" Content="Send" Command="{Binding AddCommand}" Width="77" Style="{DynamicResource FlatButtonStyle}" Margin="20,0,0,0"/>
</StackPanel>
</StackPanel>
Styles
<!-- Style Collapsed-->
<Style x:Key="stackCollapsed" TargetType="StackPanel">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=sentButton,Path=IsPressed}" Value="true">
<Setter Property="StackPanel.Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
Instead of Button use ToggleButton and bind StackPanel.Visibility to ToggleButton.IsChecked property via BooleanToVisibilityConverter converter
<ToggleButton x:Name="sentButton" Content="Add Friend" Margin="493,0,0,0" HorizontalAlignment="Left" Width="106"/>
<StackPanel Visibility="{Binding ElementName=sentButton, Path=IsChecked, Converter={StaticResource BooleanToVisibilityConverter}}">
<Label Content="Invite Friends" FontWeight="Bold" Margin="0,0,477,0" Height="32" />
<StackPanel Orientation="Horizontal" Margin="26,0,0,0">
<Label Content="Enter your friend's email" Width="222" Height="25" />
<TextBox Text="{Binding Email, UpdateSourceTrigger=PropertyChanged}" x:Name="textBoxEmail" Width="298"/>
<Button x:Name="button1" Content="Send" Command="{Binding AddCommand}" Width="77" Margin="20,0,0,0"/>
</StackPanel>
</StackPanel>
where converter is defined as below
<Window.Resources>
<ResourceDictionary>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
</ResourceDictionary>
</Window.Resources>
The problem is the Visibility property in the <StackPanel> tab takes a higher precedence than anything set in a Style or Trigger, so the Trigger never gets applied. See the Dependency Property Precedence List for more details.
To fix your current solution, move the Visibliity property out of the <StackPanel> tag and into your Style, like this :
<Style x:Key="stackCollapsed" TargetType="StackPanel">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=sentButton,Path=IsPressed}" Value="true">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
<StackPanel Style="{DynamicResource stackCollapsed}">
...
</StackPanel>
That said, I would personally recommend something like a Toggle Button with the StackPanel.Visibility bound to the ToggleButton.IsChecked, like this answer suggests.
I solved set the Children to null
stackPanel.Children.Clear();
this work if you need to show / hide the panel the first time, it doesn't work if you need to do runtime
Simple as Stackpanel.Visibility = Visibility.Collapsed.
I am new to using XAML and C# in general so this is probably an easy question but I have my XAML as so
<Page
x:Class="Tournament_Director_Windows.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Tournament_Director_Windows"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="LightGray">
<Button Style="{StaticResource AddAppBarButtonStyle}" Foreground="#FF094AB2" Click="onAddNewBowlerClick" HorizontalAlignment="Right" RenderTransformOrigin="0.4,0.508" Margin="0,10,115,679"/>
<ListView Height="648" Width="377" HorizontalAlignment="Left" VerticalAlignment="Top" x:Name="itemListView" ItemClick="itemListView_ItemClick" ItemsSource="{Binding}" IsItemClickEnabled="True" Margin="225,110,0,0">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<TextBlock TextWrapping="Wrap" Text="Bowlers" Height="54" Width="177" FontSize="50" Foreground="#FF094AB2" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="225,10,964,704"/>
<Button Style="{StaticResource RefreshAppBarButtonStyle}" Click="onSyncClick" Background="#FFF8FCFD" HorizontalAlignment="Right" Foreground="#FF094AB2" BorderBrush="#FFFBF9F9" Margin="0,10,10,679"/>
<ListView HorizontalAlignment="Left" Height="Auto" Width="220" Background="Silver" SelectionChanged="MenuListView_SelectionChanged">
<!--<ListView.Resources>
<Style TargetType="ListViewItem">
<Setter Property="Foreground" Value="#FF094AB2" />
<Setter Property="FontSize" Value="30" />
<Setter Property="Height" Value="75"/>
</Style>
</ListView.Resources>-->
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Foreground" Value="#FF094AB2" />
<Setter Property="FontSize" Value="25" />
<Setter Property="Height" Value="75"/>
<Setter Property="Padding" Value="10"/>
</Style>
</ListView.ItemContainerStyle>
<x:String>Bowlers</x:String>
<x:String>Brackets</x:String>
<x:String>Scores</x:String>
</ListView>
<ScrollViewer Height="Auto" HorizontalAlignment="Stretch" Width="754" Margin="602,110,0,10">
</ScrollViewer>
</Grid>
my question is about the ScrollViewer at the end, I have it as a set width but what I want to do is have the width fill the rest of the screen from its set position next to my ListView so no matter what screen size you have it looks the same and there is not a big space if you have a bigger screen or it gets cut off because the screen is smaller.
How can I do that?
Try to use <ColumnDefinitions> with width property "Auto" or "*" and <RowDefinitions> with height property "Auto" or "*" for grid. In this case you can manage what part of your content has permanent size and what part will resize with a window.
i got a DataTemplate for a listboxitem and i want to create a triger , so when a user click an item the background will change and also the label
my code:
<Window.Resources>
<Style x:Key="RoundedItem" TargetType="ListBoxItem">
<EventSetter Event="MouseDoubleClick" Handler="listViewItem_MouseDoubleClick" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border Name="ItemBorder" CornerRadius="10" BorderBrush="Black" BorderThickness="1" Margin="1" Background="Transparent">
<Label Name="ItemLabel" Foreground="Red" >
<ContentPresenter />
</Label>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="ItemBorder" Property="Background" Value="DeepSkyBlue" />
<Setter TargetName="ItemLabel" Property="Foreground" Value="Orange" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<DataTemplate x:Key="TitleTemplate" DataType="models:Title" >
<StackPanel>
<Image Source="{Binding ThumbFilePath}" Width="50" HorizontalAlignment="Center"/>
<Label Content="{Binding Name}" HorizontalAlignment="Center" />
<TextBlock Text="{Binding Description}" HorizontalAlignment="Center" TextWrapping="Wrap" Padding="5,5,5,5"/>
</StackPanel>
</DataTemplate>
</Window.Resources>
What happend is that the TextBlock change his color and not the label..
anyone know why ?
Thanks.
The TextBlock inherits the Foreground definition from its parents in the visual tree. The Label, on the other hand, defines the Foreground in its default style.
Your approach is "non-WPF-like" - you shouldn't wrap the ContentPresenter in a Label control.
The right approach depends on whether you want all text in the item to change its Foreground, or just the label?
[In both cases, there's no apparent benefit to using a Label in the data template - so I'll assume that the label is changed to TextBlock.]
If the answer to the above question is that all text should be changed: in the ControlTemplate of the ListBoxItem, in the trigger for IsSelected, from the seccond setter remove TargetName="ItemLabel" so the final setter is:
<Setter Property="Foreground" Value="Orange" />
This will change the foreground of the item that will affect the foreground of both TextBlocks in the data template.
If you want to affect just one of the TextBlocks:
1. remove the setter for the foreground from the control template
2. add a trigger to your data template:
<DataTemplate>
<StackPanel>
<Image .../>
<TextBlock x:Name="Text01" ..../>
<TextBlock x:Name="Text02" ..../>
</StackPanel>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}}" Value="True">
<Setter TargetName="Text01" Property="Foreground" Value="Orange"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
Side note: if you have to use Label control in your data template, bind its Foreground property to the Foreground of the list box item, like so:
<Label Foreground="{Binding Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}}"....../>
If this doesn't help, it means that your list box item inherits its foreground, so use:
<Label Foreground="{Binding TextElement.Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}}"....../>
I want to tack on to this that I was experiencing a similar problem where I'd added a ListBox.ItemTemplate to my ListBox, and the styling then did not apply to the text anymore.
What I was doing was trying to display a list of languages (CultureInfo) for the user to select from, however I wanted the native names to display, not the English name. For some reason, not all languages have their native names capitalized in their CultureInfo, and NativeName is the only instance of their name, so I needed to apply a function to the CultureInfo.NativeName to capitalize the names myself. To accomplish this, I added the ItemTemplate with a Data Template inside, on which I applied a converter.
<ListBox IsSynchronizedWithCurrentItem="True" VerticalAlignment="Center" MinHeight="200" x:Name="cbLanguages"
ItemsSource="{Binding Path=SupportedCultures, Mode=OneWay, Source={StaticResource CultureResourcesDS}}"
FontSize="24" HorizontalAlignment="Stretch" Width="300" Margin="10"
Style="{DynamicResource ListBoxTemplate}" ItemContainerStyle="{DynamicResource ListBoxItemStyle}">
<ListBox.ItemTemplate>
<DataTemplate>
<Label Content="{Binding Converter={StaticResource NativeNameConverter}}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
After a while of searching, I came across XAMeLi's answer here, and changed the Label I'd put in the DataTemplate to a TextBox, and the ListBoxItemStyle I'd created worked again.
Basically, Labels and TextBoxes have different traits that can be exploited, or can cause annoying issues in this case. Here's a good explanation with some examples of the differences: http://joshsmithonwpf.wordpress.com/2007/07/04/differences-between-label-and-textblock/