Zoom Control Template Like Expression Blend’s
-
Does anyone have any ideas on how to create a zoom control template that behaves like the actual zoom control in expression blend? The control seems to be a combination of a Textbox, Combobox, Progress Bar, and after you click down on it appears to behave as if you are moving an invisible slider control that covers the whole screen.
Sincerely, -Ron
-
Does anyone have any ideas on how to create a zoom control template that behaves like the actual zoom control in expression blend? The control seems to be a combination of a Textbox, Combobox, Progress Bar, and after you click down on it appears to behave as if you are moving an invisible slider control that covers the whole screen.
Sincerely, -Ron
I had quick go at recreating one, didn't look at the drop down functionality but that shouldn't be too hard.
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="Zoomer.ZoomWidget"
x:Name="UserControl"
d:DesignWidth="640" d:DesignHeight="480" Height="24" Width="80"><Grid x:Name="LayoutRoot"> <ProgressBar x:Name="Progress" Maximum="6400"/> <Thumb DragDelta="Thumb\_DragDelta" DragStarted="Thumb\_DragStarted" DragCompleted="Thumb\_DragCompleted" PreviewMouseLeftButtonUp="Thumb\_MouseLeftButtonUp"> <Thumb.Template> <ControlTemplate> <Border Background="#00FFFFFF" /> </ControlTemplate> </Thumb.Template> </Thumb> <TextBlock Text="{Binding Path=Value, ElementName=Progress, Mode=Default}" TextWrapping="Wrap" IsHitTestVisible="False"/> <TextBox x:Name="TextBox" Text="" Visibility="Hidden" AcceptsReturn="True" KeyUp="TextBox\_KeyUp"/> </Grid>
</UserControl>
public partial class ZoomWidget { private double totalDrag = 0; public ZoomWidget() { this.InitializeComponent(); } private void Thumb\_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e) { double delta = e.HorizontalChange - e.VerticalChange; Progress.Value += delta; totalDrag += delta; } private void Thumb\_DragStarted(object sender, System.Windows.Controls.Primitives.DragStartedEventArgs e) { Cursor = Cursors.None; } private void Thumb\_DragCompleted(object sender, System.Windows.Controls.Primitives.DragCompletedEventArgs e) { Cursor = Cursors.Arrow; } private void Thumb\_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { if(totalDrag < 1) { TextBox.Text = Progress.Value.ToString(); TextBox.Visibility = Visibility.Visible; TextBox.Focus(); TextBox.SelectAll(); } totalDrag = 0; } private void TextBox\_KeyUp(object sender, KeyEventArgs e) { if (e.Key == Key.Enter) { TextBox.Visibility = Visibility.Hidden; double newZoom; if (double.TryParse(TextBox.Text, out newZoom)) Progress.Value =
-
I had quick go at recreating one, didn't look at the drop down functionality but that shouldn't be too hard.
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="Zoomer.ZoomWidget"
x:Name="UserControl"
d:DesignWidth="640" d:DesignHeight="480" Height="24" Width="80"><Grid x:Name="LayoutRoot"> <ProgressBar x:Name="Progress" Maximum="6400"/> <Thumb DragDelta="Thumb\_DragDelta" DragStarted="Thumb\_DragStarted" DragCompleted="Thumb\_DragCompleted" PreviewMouseLeftButtonUp="Thumb\_MouseLeftButtonUp"> <Thumb.Template> <ControlTemplate> <Border Background="#00FFFFFF" /> </ControlTemplate> </Thumb.Template> </Thumb> <TextBlock Text="{Binding Path=Value, ElementName=Progress, Mode=Default}" TextWrapping="Wrap" IsHitTestVisible="False"/> <TextBox x:Name="TextBox" Text="" Visibility="Hidden" AcceptsReturn="True" KeyUp="TextBox\_KeyUp"/> </Grid>
</UserControl>
public partial class ZoomWidget { private double totalDrag = 0; public ZoomWidget() { this.InitializeComponent(); } private void Thumb\_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e) { double delta = e.HorizontalChange - e.VerticalChange; Progress.Value += delta; totalDrag += delta; } private void Thumb\_DragStarted(object sender, System.Windows.Controls.Primitives.DragStartedEventArgs e) { Cursor = Cursors.None; } private void Thumb\_DragCompleted(object sender, System.Windows.Controls.Primitives.DragCompletedEventArgs e) { Cursor = Cursors.Arrow; } private void Thumb\_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { if(totalDrag < 1) { TextBox.Text = Progress.Value.ToString(); TextBox.Visibility = Visibility.Visible; TextBox.Focus(); TextBox.SelectAll(); } totalDrag = 0; } private void TextBox\_KeyUp(object sender, KeyEventArgs e) { if (e.Key == Key.Enter) { TextBox.Visibility = Visibility.Hidden; double newZoom; if (double.TryParse(TextBox.Text, out newZoom)) Progress.Value =
Wow Dave. Thanks. It seems like a pretty sincere beginning to me. And it works. :) How'd you find out about Thumb? It looks like some of the key concepts are: - Layer controls on top of each other in z order in a grid. - The "value" of the control is actually stored in the progress bar value. - The text box is only visible on mouse up when a drag hasn't started. - Use Thumb to capture mouse drag. The value resulting from a drag is not quite what I expected. If I begin a drag and wiggle my mouse back and forth to the right of the initial drag point the value just kept going up. I'd rather it be absolute relative to the start point. I was also hoping to limit the value between 0.0 and 100.0 but be able to drag up and down across the whole screen to get fine granularity. I tried adding dragstartValue as follows which sets the value relative to the start point. It works but I can't figure out the range scaling relative to the sizeof the user's screen. Any ideas?
public partial class ZoomWidget : UserControl { private double totalDrag = 0; private double dragstartValue = 0; public ZoomWidget() { InitializeComponent(); } private void Thumb_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e) { double delta = e.HorizontalChange - e.VerticalChange; Progress.Value = dragstartValue + delta; totalDrag += delta; } private void Thumb_DragStarted(object sender, System.Windows.Controls.Primitives.DragStartedEventArgs e) { dragstartValue = Progress.Value; Cursor = Cursors.ScrollAll; } private void Thumb_DragCompleted(object sender, System.Windows.Controls.Primitives.DragCompletedEventArgs e) { Cursor = Cursors.Arrow; Debug.Print("Thumb_DragCompleted()"); } private void Thumb_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { if (totalDrag < 1) { TextBox.Text = Progress.Value.ToString(); TextBox.Visibility = Visibility.Visible; TextBox.Focus(); TextBox.SelectAll(); } totalDrag = 0; dragstartValue = 0; } //... }
It is a really great start. Thanks.Sincerely, -Ron
-
Wow Dave. Thanks. It seems like a pretty sincere beginning to me. And it works. :) How'd you find out about Thumb? It looks like some of the key concepts are: - Layer controls on top of each other in z order in a grid. - The "value" of the control is actually stored in the progress bar value. - The text box is only visible on mouse up when a drag hasn't started. - Use Thumb to capture mouse drag. The value resulting from a drag is not quite what I expected. If I begin a drag and wiggle my mouse back and forth to the right of the initial drag point the value just kept going up. I'd rather it be absolute relative to the start point. I was also hoping to limit the value between 0.0 and 100.0 but be able to drag up and down across the whole screen to get fine granularity. I tried adding dragstartValue as follows which sets the value relative to the start point. It works but I can't figure out the range scaling relative to the sizeof the user's screen. Any ideas?
public partial class ZoomWidget : UserControl { private double totalDrag = 0; private double dragstartValue = 0; public ZoomWidget() { InitializeComponent(); } private void Thumb_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e) { double delta = e.HorizontalChange - e.VerticalChange; Progress.Value = dragstartValue + delta; totalDrag += delta; } private void Thumb_DragStarted(object sender, System.Windows.Controls.Primitives.DragStartedEventArgs e) { dragstartValue = Progress.Value; Cursor = Cursors.ScrollAll; } private void Thumb_DragCompleted(object sender, System.Windows.Controls.Primitives.DragCompletedEventArgs e) { Cursor = Cursors.Arrow; Debug.Print("Thumb_DragCompleted()"); } private void Thumb_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { if (totalDrag < 1) { TextBox.Text = Progress.Value.ToString(); TextBox.Visibility = Visibility.Visible; TextBox.Focus(); TextBox.SelectAll(); } totalDrag = 0; dragstartValue = 0; } //... }
It is a really great start. Thanks.Sincerely, -Ron
-
I had quick go at recreating one, didn't look at the drop down functionality but that shouldn't be too hard.
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="Zoomer.ZoomWidget"
x:Name="UserControl"
d:DesignWidth="640" d:DesignHeight="480" Height="24" Width="80"><Grid x:Name="LayoutRoot"> <ProgressBar x:Name="Progress" Maximum="6400"/> <Thumb DragDelta="Thumb\_DragDelta" DragStarted="Thumb\_DragStarted" DragCompleted="Thumb\_DragCompleted" PreviewMouseLeftButtonUp="Thumb\_MouseLeftButtonUp"> <Thumb.Template> <ControlTemplate> <Border Background="#00FFFFFF" /> </ControlTemplate> </Thumb.Template> </Thumb> <TextBlock Text="{Binding Path=Value, ElementName=Progress, Mode=Default}" TextWrapping="Wrap" IsHitTestVisible="False"/> <TextBox x:Name="TextBox" Text="" Visibility="Hidden" AcceptsReturn="True" KeyUp="TextBox\_KeyUp"/> </Grid>
</UserControl>
public partial class ZoomWidget { private double totalDrag = 0; public ZoomWidget() { this.InitializeComponent(); } private void Thumb\_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e) { double delta = e.HorizontalChange - e.VerticalChange; Progress.Value += delta; totalDrag += delta; } private void Thumb\_DragStarted(object sender, System.Windows.Controls.Primitives.DragStartedEventArgs e) { Cursor = Cursors.None; } private void Thumb\_DragCompleted(object sender, System.Windows.Controls.Primitives.DragCompletedEventArgs e) { Cursor = Cursors.Arrow; } private void Thumb\_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { if(totalDrag < 1) { TextBox.Text = Progress.Value.ToString(); TextBox.Visibility = Visibility.Visible; TextBox.Focus(); TextBox.SelectAll(); } totalDrag = 0; } private void TextBox\_KeyUp(object sender, KeyEventArgs e) { if (e.Key == Key.Enter) { TextBox.Visibility = Visibility.Hidden; double newZoom; if (double.TryParse(TextBox.Text, out newZoom)) Progress.Value =
Dave, Great post. Can you edit your post and move the last line out of the PRE tag. I can't see the right edit to vote.
Cheers, Karl
» CodeProject 2008 MVP » Microsoft MVP - Client App Dev My Blog | Mole's Home Page | MVP ProfileJust a grain of sand on the worlds beaches.
-
Also: how do you think they put the % sign on the value that displays in the text block? Since the value is bound to Progress.Value, I guess the real question is how can one add to or format a string that is in part based on a bound value?
Sincerely, -Ron
You can use a ValueConverter to add the % symbol and other formatting settings, I seem to recall that there was a new property added in .net 3.5 that allows you to set the ToString format in the binding directly but I could not find the details, maybe that was the next release. You could divide delta by some value to get it more precise, I tried some alterations to get better dragging behavior, the following changes allow you to go from 0-max in half of the screen.
private double baseValue = 0;
private DateTime dragStart;
public ZoomWidget()
{
this.InitializeComponent();
}private void Thumb_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
{
double screenX = SystemParameters.FullPrimaryScreenWidth;
double screenY = SystemParameters.FullPrimaryScreenHeight;
double delta = ((e.HorizontalChange/(screenX/2)) - (e.VerticalChange/(screenY/2))) *Progress.Maximum;Progress.Value = baseValue + delta;
}
private void Thumb_DragStarted(object sender, System.Windows.Controls.Primitives.DragStartedEventArgs e)
{
Cursor = Cursors.None;
baseValue = Progress.Value;
dragStart = DateTime.Now;
}private void Thumb_DragCompleted(object sender, System.Windows.Controls.Primitives.DragCompletedEventArgs e)
{
Cursor = Cursors.Arrow;
}private void Thumb_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if((DateTime.Now-dragStart).Milliseconds < 200)
{
TextBox.Text = Progress.Value.ToString();
TextBox.Visibility = Visibility.Visible;
TextBox.Focus();
TextBox.SelectAll();
}
}private void TextBox_KeyUp(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
TextBox.Visibility = Visibility.Hidden;
double newZoom;
if (double.TryParse(TextBox.Text, out newZoom))
Progress.Value = newZoom;
}
}modified on Monday, April 14, 2008 1:32 PM
-
Dave, Great post. Can you edit your post and move the last line out of the PRE tag. I can't see the right edit to vote.
Cheers, Karl
» CodeProject 2008 MVP » Microsoft MVP - Client App Dev My Blog | Mole's Home Page | MVP ProfileJust a grain of sand on the worlds beaches.
I was using <pre> and <code> tags that ie didn't seem to like.
-
You can use a ValueConverter to add the % symbol and other formatting settings, I seem to recall that there was a new property added in .net 3.5 that allows you to set the ToString format in the binding directly but I could not find the details, maybe that was the next release. You could divide delta by some value to get it more precise, I tried some alterations to get better dragging behavior, the following changes allow you to go from 0-max in half of the screen.
private double baseValue = 0;
private DateTime dragStart;
public ZoomWidget()
{
this.InitializeComponent();
}private void Thumb_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
{
double screenX = SystemParameters.FullPrimaryScreenWidth;
double screenY = SystemParameters.FullPrimaryScreenHeight;
double delta = ((e.HorizontalChange/(screenX/2)) - (e.VerticalChange/(screenY/2))) *Progress.Maximum;Progress.Value = baseValue + delta;
}
private void Thumb_DragStarted(object sender, System.Windows.Controls.Primitives.DragStartedEventArgs e)
{
Cursor = Cursors.None;
baseValue = Progress.Value;
dragStart = DateTime.Now;
}private void Thumb_DragCompleted(object sender, System.Windows.Controls.Primitives.DragCompletedEventArgs e)
{
Cursor = Cursors.Arrow;
}private void Thumb_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if((DateTime.Now-dragStart).Milliseconds < 200)
{
TextBox.Text = Progress.Value.ToString();
TextBox.Visibility = Visibility.Visible;
TextBox.Focus();
TextBox.SelectAll();
}
}private void TextBox_KeyUp(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
TextBox.Visibility = Visibility.Hidden;
double newZoom;
if (double.TryParse(TextBox.Text, out newZoom))
Progress.Value = newZoom;
}
}modified on Monday, April 14, 2008 1:32 PM
-
You can use a ValueConverter to add the % symbol and other formatting settings, I seem to recall that there was a new property added in .net 3.5 that allows you to set the ToString format in the binding directly but I could not find the details, maybe that was the next release. You could divide delta by some value to get it more precise, I tried some alterations to get better dragging behavior, the following changes allow you to go from 0-max in half of the screen.
private double baseValue = 0;
private DateTime dragStart;
public ZoomWidget()
{
this.InitializeComponent();
}private void Thumb_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
{
double screenX = SystemParameters.FullPrimaryScreenWidth;
double screenY = SystemParameters.FullPrimaryScreenHeight;
double delta = ((e.HorizontalChange/(screenX/2)) - (e.VerticalChange/(screenY/2))) *Progress.Maximum;Progress.Value = baseValue + delta;
}
private void Thumb_DragStarted(object sender, System.Windows.Controls.Primitives.DragStartedEventArgs e)
{
Cursor = Cursors.None;
baseValue = Progress.Value;
dragStart = DateTime.Now;
}private void Thumb_DragCompleted(object sender, System.Windows.Controls.Primitives.DragCompletedEventArgs e)
{
Cursor = Cursors.Arrow;
}private void Thumb_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if((DateTime.Now-dragStart).Milliseconds < 200)
{
TextBox.Text = Progress.Value.ToString();
TextBox.Visibility = Visibility.Visible;
TextBox.Focus();
TextBox.SelectAll();
}
}private void TextBox_KeyUp(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
TextBox.Visibility = Visibility.Hidden;
double newZoom;
if (double.TryParse(TextBox.Text, out newZoom))
Progress.Value = newZoom;
}
}modified on Monday, April 14, 2008 1:32 PM
That's a nice little control you've put together there Dave. 5.
Deja View - the feeling that you've seen this post before.