I'm applying EntranceThemeTransition to StackPanel that contains bunch of controls. When I show a popup everything works fine except TextBlocks that jump a little after animation.
Here is a video of that:
http://screencast.com/t/VXSiti6Mh
Here is code I'm using:
<StackPanel Margin="40">
<StackPanel.ChildrenTransitions>
<TransitionCollection>
<EntranceThemeTransition FromHorizontalOffset="100" />
</TransitionCollection>
</StackPanel.ChildrenTransitions>
<TextBlock Text="Filter Results" />
<TextBlock >Show</TextBlock>
</StackPanel>
The popup itself has PaneThemeTransition set as it's Transition.
Any ideas why it could be happening?
Have you tried:
UseLayoutRounding="True" SnapsToDevicePixels="True"
on the container.
I found a workaround - wrap each textblock with StackPanel. Clearly it's not ideal but it works.
I still wonder if there is a way to fix it without hacks...
Related
This may be a no-brainer for the WPF cognoscenti, but I'd like to know if there's a simple way to put text on the WPF ProgressBar. To me, an empty progress bar looks naked. That's screen real estate that could carry a message about what is in progress, or even just add numbers to the representation. Now, WPF is all about containers and extensions and I'm slowly wrapping my mind around that, but since I don't see a "Text" or "Content" property, I'm thinking I'm going to have to add something to the container that is my progress bar. Is there a technique or two out there that is more natural than my original WinForms impulses will be? What's the best, most WPF-natural way to add text to that progress bar?
Both of the prior responses (creating a new CustomControl or an Adorner) are better practices, but if you just want quick and dirty (or to understand visually how to do it) then this code would work:
<Grid Width="300" Height="50">
<ProgressBar Value="50" />
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center">
My Text
</TextBlock>
</Grid>
Just keep in mind that the z-index is such that the last item listed will be on top.
Also, if you don't have Kaxaml yet, be sure to pick it up - it is great for playing with XAML when you're trying to figure things out.
This can be very simple (unless there are alot of ways getting this to work).
You could use Style to get this done or you just overlay a TextBlock and a ProgressBar.
I personally use this to show the percentage of the progress when waiting for completion.
To keep it very simple I only wanted to have one Binding only,
so I attached the TextBock.Text to the ProgressBar.Value.
Then just copy the Code to get it done.
<Grid>
<ProgressBar Minimum="0"
Maximum="100"
Value="{Binding InsertBindingHere}"
Name="pbStatus" />
<TextBlock Text="{Binding ElementName=pbStatus, Path=Value, StringFormat={}{0:0}%}"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Grid>
Here is how this could look like:
Check out WPF Tutorial for the full post.
If you are needing to have a reusable method for adding text, you can create a new Style/ControlTemplate that has an additional TextBlock to display the text. You can hijack the TextSearch.Text attached property to set the text on a progress bar.
If it doesn't need to be reusable, simply put the progress bar in a Grid and add a TextBlock to the grid. Since WPF can compose elements together, this will work nicely.
If you want, you can create a UserControl that exposes the ProgressBar and TextBlock as public properties, so it would be less work than creating a custom ControlTemplate.
You could use an Adorner to display text over top of it.
See MSDN article on Adorners
You would create a class that inherits from the Adorner class. Override the OnRender method to draw the text that you want. If you want you could create a dependency property for your custom Adorner that contains the text that you want to display. Then use the example in the link I mentioned to add this Adorner to your progress bar's adorner layer.
ProgressBar with Text and Binding from 2 Properties ( Value/Maximum value ):
<Grid>
<ProgressBar Name="pbUsrLvl"
Minimum="1"
Maximum="99"
Value="59"
Margin="5"
Height="24" Foreground="#FF62FF7F"/>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock.Text>
<MultiBinding StringFormat="{}UserLvl:{0}/{1}">
<Binding Path="Value" ElementName="pbUsrLvl" />
<Binding Path="Maximum" ElementName="pbUsrLvl" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</Grid>
Rezult:
The same but with % of progress :
<Grid>
<ProgressBar Name="pbLifePassed"
Minimum="0"
Value="59"
Maximum="100"
Margin="5" Height="24" Foreground="#FF62FF7F"/>
<TextBlock Text="{Binding ElementName=pbLifePassed, Path=Value, StringFormat={}{0:0}%}"
HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
Right click ProgressBar, and click Edit Template > Edit a Copy.
Then put the TextBlock as shown below just above the closing tag of Grid in the Style generated by VS.
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="2"/>
<TextBlock Background="Transparent" Text="work in progress" Foreground="Black" TextAlignment="Center"/>
</Grid>
<ControlTemplate.Triggers>
This is based on the given answers.
Since I´m using MahApps Metro, I ended up with this:
<Grid>
<metro:MetroProgressBar x:Name="pbar" Value="50" Height="20"></metro:MetroProgressBar>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding ElementName=pbar, Path=Value, StringFormat={}{0:0}%}"></TextBlock>
</Grid>
If you want to use the normal bar with Metro Style:
<Grid>
<ProgressBar x:Name="pbar" Value="50" Height="20" Style="{StaticResource MetroProgressBar}"></ProgressBar>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding ElementName=pbar, Path=Value, StringFormat={}{0:0}%}"></TextBlock>
</Grid>
Same without Style:
<Grid>
<ProgressBar x:Name="pbar" Value="60" Height="20" Style="{x:Null}"></ProgressBar>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding ElementName=pbar, Path=Value, StringFormat={}{0:0}%}"></TextBlock>
</Grid>
What is Happening?
You have your progressbar and simply just lay text over it.
So you just use your progressbar as you would.
Put the progressbar in a grid and lay an textblock in it.
Then you can text as you wish or grab the current percenteage wich is the value from the progressbar.
I'm trying to get a ContentControl to apply a ContentThemeTransitionwhere the content will be a string, so when the string changes via a binding the new string will animate in. I can't use ContentThemeTransition with a TextBlock as this doesn't derive from ContentControl.
Here is some example XAML that shows the problem. If I edit the text in the Textbox (which represents the text in my ViewModel that the ContentControl is really bound to) I would expect the Text shown in the ContentControl to animate in, but it doesn't.
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBox Grid.Row="0" x:Name="text" Text="Hello" Width="100" Height="30"/>
<ContentControl Grid.Row="1" Width="100" Height="100" Content="{Binding ElementName=text , Path=Text}">
<ContentControl.Transitions>
<TransitionCollection>
<ContentThemeTransition HorizontalOffset="40"/>
</TransitionCollection>
</ContentControl.Transitions>
</ContentControl>
</Grid>
What am I doing wrong?
Update
I am getting somewhere now. If you replace the ContentControl XAML to
<ContentPresenter Background="Black" Foreground="Red" Grid.Row="1" Width="100" Height="100" Content="{Binding ElementName=text , Path=Text}">
<ContentPresenter.ContentTransitions>
<TransitionCollection>
<ContentThemeTransition VerticalOffset="-100"/>
</TransitionCollection>
</ContentPresenter.ContentTransitions>
</ContentPresenter>
then it works. Oddly, with the VerticalOffset =-100 as above the new value animates down outside of the ContentControli.e. its visible outside the bounds of the control. Anyone know how to change things so the animation only appears within the confines of the ContentPresenter?
Tested by my side, your first <ContentThemeTransition HorizontalOffset="40"/> and second <ContentThemeTransition VerticalOffset="-100"/> both work but only for the first time, you can enlarge the HorizontalOffset for testing and check if it works.
Since you expected that the animation should work every time the text is changed, I think you will need to create a animation which targets the Text of TextBlock directly instead of targeting the Content of ContentControl.
In this scenario, XAML Behaviors will be a good helper. You can refer to #Jerry Nixon - MSFT's answer in thread: How to animate TextBlock when its value changes in WinRT XAML?
Update:
My mistake that I only noticed that you changed HorizontalOffset to VerticalOffset. You actually also changed ContentControl to ContentPresenter.
According to the UI coordinate of UWP, since your animation target the ContentPresenter, then consider the left-top point of your ContentPresent is (0, 0). When you set <ContentThemeTransition VerticalOffset="-100"/>, it will transit from up (0, -100) back to (0, 0) and it will definitely animate outside of your ContentPresent, I think it is designed to be so, and we're not able change it. Here I can only suggest that modifying the transition from down to up like <ContentThemeTransition VerticalOffset="100"/>, it will help a little here but eventually it changes your animation, so I don't think this will be a good approach.
I'm trying to implement a nice-looking horizontally scrolled gridview inside my app. I have already implemented it using the Q42.WinRT library like this:
<Canvas>
<StackPanel Orientation="Horizontal" Height="768">
<StackPanel.RenderTransform>
<CompositeTransform
TranslateX="{Binding ElementName=MyScrollViewer, Path=HorizontalOffset, Converter={StaticResource ParallaxConverter}}" />
</StackPanel.RenderTransform>
<Image Source="/Assets/3.jpg" Width="1366" Stretch="UniformToFill"/>
<Image Source="/Assets/1.jpg" Stretch="UniformToFill"/>
<Image Source="/Assets/2.jpg" Stretch="UniformToFill"/>
</StackPanel>
</Canvas>
<ScrollViewer
x:Name="MyScrollViewer"
HorizontalScrollMode="Enabled"
HorizontalScrollBarVisibility="Auto"
VerticalScrollMode="Disabled"
VerticalAlignment="Center"
Height="768">
<GridView>
//...my gridview goes here
</GridView> </ScrollViewer>
Everything works fine, however in my app I need to use semantic zoom, and I found that semantic zoom does NOT WORK properly when put inside a ScrollViewer.
Generally all the solutions for parallactic backgrounds that I found on the internet implement some kind of functionality over a scrollviewer, which is unfortunate for me as I cannot use it.
Can anybody think of another way to achieve the desired effect?
Generally putting GridViews inside a ScrollViewer is not a great idea since they already have ScrollViewers inside of them...
You should put your 2 GridViews inside a SemanticZoom.
Perhaps you could edit the template for your GridView and put a parallax background in there - perhaps as a Canvas with some content that responds to the ViewChanged events on the GridView.
EDIT*
You inspired me to try to write a ParallaxBackgroundBehavior for the Toolkit. :)
You can see an early version here. There is also a sample included.
Hello and thanks for the help. I have a Treeview that I am populating with a Hierarchical data template, and currently the bottom nodes have a tooltip that generates a small stack panel that is populated with data specific to the item the mouse hovers over. I also have a button sitting in the tooltip, however, as the tooltip does not persist when the mouse moves over it, I am unable to make use of the button like I need to. My xaml looks like this:
<!--=========================== Hierarchical Data template for tree view -->
<!--template for bottom nodes-->
<sdk:HierarchicalDataTemplate x:Key="ModTemplate" ItemsSource="{Binding ApplicationModules}">
<StackPanel Orientation="Horizontal" > <!--======tooltip style to handle format for callout window============-->
<ToolTipService.ToolTip>
<ToolTip HorizontalOffset="0" VerticalOffset="0" Style="{StaticResource ModuleToolTipStyle}">
<StackPanel Width="150" Height="auto" >
<TextBlock Text="Module Info" FontWeight="Bold" TextAlignment="Center"/>
<TextBlock Text="Module State:" FontWeight="Bold" />
<TextBlock Text="{Binding Path=ModInfo.ModuleState}" />
<TextBlock Text="Module Start Time:" FontWeight="Bold" />
<TextBlock Text="{Binding Path=ModInfo.ModuleStartTime}"/>
<TextBlock Text="Module Down Time:" FontWeight="Bold"/>
<TextBlock Text="{Binding Path=ModInfo.ModuleDownTime}" />
<Button Content="More Info" Width="75"></Button>
</StackPanel>
</ToolTip>
</ToolTipService.ToolTip>
<!--============end tooltip style for callout window===================-->
<ContentPresenter Margin="0 0 4 0" Content="{Binding Icon}" />
<TextBlock FontStyle="Italic" Text="{Binding Path=ModuleName}" />
</StackPanel>
</sdk:HierarchicalDataTemplate>
I would like the tooltip to persist when the mouse moves over it so that I can wire an event to the button. How can I achieve this? Thanks again for the help.
You have a couple options to accomplish your goal that I'm aware of. You can go check out the Silverlight Advanced Tooltips project over on codeplex which does what you want (though I personally have not used it so can't give any kind of review.)
Or you can make your own with some creativity. If it were me I would probably skip all that mess, forget the ToolTipService all together and just make my own to dress it up since to a user, what you're providing isn't what they're used to in terms of a tooltip expectation anyway and have cross more over to a callout or popout functionality. I can make an example as soon as I get some freed up time if option #1 doesn't work for you but I hope it does. Essentially both my way, and that project link I provided would do the same thing, which is provide a delay after the MouseLeave event of what it's attached to so the user can get to it before it disappears. Then hand off its visibility condition to that object. Let me know if this doesnt work and I can give you an alternative example using nothing but XAML.
I have generated XAML file from Windows Forms, and with the process calculated right and bottom margins because they do not exist in Forms. I have this output:
<Grid>
<TextBox Width="129" Height="18" Margin="36,46,278,686" />
...
<TextBox Width="54" Height="18" Margin="345,705,83,31" />
<TextBox Width="54" Height="18" Margin="345,728,83,8" />
<TextBox Width="54" Height="18" Margin="345,770,83,-34" />
...
</Grid>
The problem is that Content of Grid is too large, even for the designer, so scroll bar is generated in win forms. However, this is not case in WPF, so I try adding ScrollViewer around it. But it only scrolls down to content with positive bottom margin. Controls with negative margins are not shown anywhere.
Any idea how to solve this is appreciated.
The Grid is the wrong thing for this task. If you're going to do the positioning yourself, you should use a Canvas and then use Canvas.Left and Canvas.Top to position it. You don't need the Bottom or Right values since you seem to know the Width and Height.
I believe you should be able to use the ScrollViewer around the Canvas object too.