简体   繁体   中英

WPF bind slider's mouseposition value to textblock

I have a slider with minimum 0 and max 100.

I have a popup window that is visible when I mouseover the slider.
Currently, I binded the popup with the slider value.

What I want is:
When I move the mouse over the slider, I want to see value that suppose to be in that position.

For example:
在此处输入图片说明

My XAML:

<Window x:Class="WPFMavka.VideoPlayer"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WPFMavka"
        Title="MainWindow" WindowStyle="None" Width="1920" Height="1080" WindowState="Maximized" KeyboardNavigation.TabNavigation="None" Closing="Window_Closing">
    <Grid Name="tst">
        <local:MetroSlider x:Name="bla" MouseMove="Rectangle_MouseMove" MouseLeave="Rectangle_MouseLeave" IsMoveToPointEnabled="True" HorizontalAlignment="Left" Width="542" VerticalAlignment="Top" Margin="116,839,0,0" Value="0" Style="{DynamicResource SliderStyle1}" Height="66" AutoToolTipPrecision="0" AutoToolTipPlacement="TopLeft"/>
        <Popup Name="floatingTip" AllowsTransparency="True" Placement="Relative"  PlacementTarget="{Binding ElementName=bla}">
            <Border BorderBrush="Black" BorderThickness="1" Padding="4">
                <TextBlock Text="{Binding ElementName=bla, Path=Value}"></TextBlock>
            </Border>
        </Popup>
    </Grid>
</Window>

My Code-Behind:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace WPFMavka
{
    /// <summary>
    /// Interaction logic for VideoPlayer.xaml
    /// </summary>
    public partial class VideoPlayer : Window
    {
        public VideoPlayer()
        {
            InitializeComponent();
        }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            Environment.Exit(1);
        }

        private void Rectangle_MouseMove(object sender, MouseEventArgs e)
        {
            if (!floatingTip.IsOpen) { floatingTip.IsOpen = true; }

            Point currentPos = e.GetPosition(bla);

            floatingTip.HorizontalOffset = currentPos.X-14;
            floatingTip.VerticalOffset = -32;
        }

        private void Rectangle_MouseLeave(object sender, MouseEventArgs e)
        {
            floatingTip.IsOpen = false;
        }
    }
}

Found a better solution - changing the TextBlock onMouseOver the slide > I get the current position of mouse on the slider and then uses .ValueFromPoint()

XAML:

<Window x:Class="WPFMavka.VideoPlayer"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WPFMavka"
        Title="MainWindow" WindowStyle="None" Width="1920" Height="1080" WindowState="Maximized" KeyboardNavigation.TabNavigation="None" Closing="Window_Closing">
    <Grid Name="tst">
        <local:MetroSlider x:Name="slider" MouseMove="slider_MouseMove" MouseLeave="slider_MouseLeave" IsMoveToPointEnabled="True" HorizontalAlignment="Left" Width="746" VerticalAlignment="Top" Margin="330,851,0,0" Value="0" Style="{DynamicResource SliderStyle1}" Height="44"/>
        <Popup Name="floatingTip" AllowsTransparency="True" Placement="Relative"  PlacementTarget="{Binding ElementName=slider}">
            <Border Name="floatingTipBorder" BorderBrush="Black" BorderThickness="1" Padding="4">
                <TextBlock Name="sliderTextBlock"/>
            </Border>
        </Popup>
    </Grid>
</Window>

Code-Behind:

private void slider_MouseMove(object sender, MouseEventArgs e)
{
   if (!floatingTip.IsOpen) { floatingTip.IsOpen = true; }

   Point currentPos = e.GetPosition(slider);
   Track _track = slider.Template.FindName("PART_Track", slider) as Track;

   sliderTextBlock.Text = _track.ValueFromPoint(currentPos).ToString();

   floatingTip.HorizontalOffset = currentPos.X -(floatingTipBorder.ActualWidth / 2);
   floatingTip.VerticalOffset = -32;
}

private void slider_MouseLeave(object sender, MouseEventArgs e)
{
   floatingTip.IsOpen = false;
}

You can use AttachedCommand s for this. You can download the library from here . So in this case you could do something like:

<Window x:Class="WPFMavka.VideoPlayer"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WPFMavka"
        xmlns:AttachedCommand="clr-namespace:AttachedCommandBehavior;assembly=AttachedCommandBehavior" 
        Title="MainWindow" 
        WindowStyle="None" 
        Width="1920" 
        Height="1080" 
        WindowState="Maximized" 
        KeyboardNavigation.TabNavigation="None" 
        Closing="Window_Closing">
    <Grid Name="tst">
        <local:MetroSlider x:Name="bla" 
                           MouseMove="Rectangle_MouseMove" 
                           MouseLeave="Rectangle_MouseLeave" 
                           IsMoveToPointEnabled="True" 
                           HorizontalAlignment="Left" 
                           Width="542" VerticalAlignment="Top" 
                           Margin="116,839,0,0" 
                           Value="0" 
                           Style="{DynamicResource SliderStyle1}" 
                           Height="66" AutoToolTipPrecision="0" 
                           AutoToolTipPlacement="TopLeft"
                           AttachedCommand:CommandBehavior.Event="MouseMove" 
                           AttachedCommand:CommandBehavior.Command="{Binding UpdateCurrentMouseTimeCommand}" 
                           AttachedCommand:CommandBehavior.CommandParameter="{Binding ElementName=Bla, Path=Value}"/>
        <Popup Name="floatingTip" AllowsTransparency="True" 
               Placement="Relative" 
               PlacementTarget="{Binding ElementName=bla}">
            <Border BorderBrush="Black" BorderThickness="1" Padding="4">
                <TextBlock Text="{Binding CurrentMouseTime, NotifyOnSourceUpdated=True, Mode=OneWay}" />
            </Border>
        </Popup>
    </Grid>
</Window>

Then in your command UpdateCurrentMouseTimeCommand you set the property

private string currentMouseTime = String.Empty;
public string CurrentMouseTime
{
    get { return value; }
    set 
    {
        if (currentMouseTime == value)
            return;
        currentMouseTime = value;
        OnPropertyChanged("CurrentMouseTime");
    }
}

Where the containing class must implement INotifyPropertyChanged .

I hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM