binding slider value in MVVM

10,273

Solution 1

Maybe this is what you want:

<StackPanel>
    <ListBox x:Name="ImageListBox" IsSynchronizedWithCurrentItem="True">
        <ListBoxItem>Image1</ListBoxItem>
        <ListBoxItem>Image2</ListBoxItem>
        <ListBoxItem>Image3</ListBoxItem>
        <ListBoxItem>Image4</ListBoxItem>
    </ListBox>
    <Slider Value="{Binding ElementName=ImageListBox, Path=SelectedIndex}" 
            Maximum="{Binding ElementName=ImageListBox, Path=Items.Count}"/>
</StackPanel>

You probably want to handle the max value nicer than in this sample

Solution 2

In your code the value of slider is bound to CurrentImage index, so when you change the value of slider then the index of the current image will be changed. Assumed that the current image index is 5 then your slider’s value will be 5 then if you move the slider pointer to a position like 10 then the Current image index will be set to 10 it means that your current image will be modified, so it means that it would not navigate to the 10th element of list, but it modifies the index of the image (with index of 5) and set its index to 10, in other words, you would not have a image with index of 5 anymore and 2 of your images are going to have the same index (10).

As a solution, you can add another property like “Index” into your viewmodel, and bind the slider value to that one, so at get method return the index of the selected item in list, and at the set method change the selected item in the list and call OnPropertyChanged and pass “Index” as the parameter.

Share:
10,273
Admin
Author by

Admin

Updated on June 04, 2022

Comments

  • Admin
    Admin almost 2 years

    I have a problem in slider value data binding in MVVM. When value gets changed my expected value isn’t achieved. How can I solve my problem?
    I have a listbox, a slider and a textblock. listbox is bound to ListImage, slider value and textblock text is bound to CurrentImage. One button with command navigate the lisbox item. CurrentImage is a property in the viewmodel. When I change slider’s setter, new value of setter put to current value of slider’s setter and the arrangement of listbox gets corrupted. For example when value of my slider’s setter set to 50 and I change value of slider to 10 again. My slider value navigate from 10 to 50 and not more. It must be navigate whole of the listbox but it can’t. There is my code:

    XAML:

    <TextBlock Text="{Binding CurrentImage.Index}"/>
    <Slider Height="23" HorizontalAlignment="Left" Margin="12,305,0,0" Name="slider1" VerticalAlignment="Top" Width="479" Maximum="{Binding ListImage.Count, Mode=OneTime}"
                  Value="{Binding CurrentImage.Index, Mode=TwoWay}"
                  SmallChange="1" />
    <Button Content="{Binding DisplayPlay}" Command="{Binding PlayCommand}" Height="23" HorizontalAlignment="Left" Margin="507,305,0,0" Name="button1" VerticalAlignment="Top" Width="75" />
    <ListBox Height="129" HorizontalAlignment="Left"  Margin="12,334,0,0" ItemsSource="{Binding ListImage}" SelectedItem="{Binding CurrentImage,Mode=TwoWay}" 
                     VerticalAlignment="Top" Width="472">
    

    viewmodel:

    public class MainViewModel : ViewModelBase
    {
        public ICommand PlayCommand { get; set; }
        private DispatcherTimer _Timer;
        public ImageDTO Image { get; set;}
        DataAccess AC = new DataAccess();
        public byte[] Bytes { get; set; }
        public MainViewModel()
        {
            ListImage = AC.OpenImages();
            CurrentImage = ListImage[0];
            Bytes = CurrentImage.Bytes;
            this.PlayCommand = new DelegateCommand(Play, CanPlay);
            DisplayPlay = "Play";
            _Timer = new DispatcherTimer();
            _Timer.Interval = new TimeSpan(0, 0, 0, 0, 2000 / 30);
            _Timer.Tick += new EventHandler(timer_Tick);
        }
    
        private string _DisplayPlay;
        public string DisplayPlay
        {
            get { return _DisplayPlay; }
            set
            {
                if (_DisplayPlay != value)
                {
                    _DisplayPlay = value;
                    OnPropertyChanged("DisplayPlay");
                }
            }
        }
    
        private List<ImageDTO> _ListImage;
        public List<ImageDTO> ListImage
        {
            get { return _ListImage; }
            set
            {
                if (_ListImage != value)
                    _ListImage = value;
                    OnPropertyChanged("ListImage");
            }
        }
    
        private ImageDTO _CurrentImage;
        public ImageDTO CurrentImage
        {
            get { return _CurrentImage; }
            set
            {
                if (_CurrentImage != value)
                {
                    _CurrentImage = value;
                    OnPropertyChanged("CurrentImage");
                }
            }
        }
    
        public bool CanPlay(object parameter)
        {
            return true;
        }
        public void Play(object parameter)
        {
            if (DisplayPlay == "Play")
            {
                DisplayPlay = "Pause";
                _Timer.Start();
            }
            else
            {
                _Timer.Stop();
                DisplayPlay = "Play";
            }
        }
    
        private void timer_Tick(object sender, EventArgs e)
        {
            int position = ListImage.FindIndex(x => x.Index == CurrentImage.Index);
            position++;
            if (position == ListImage.Count)
            {
                position = 0;
            }
            else
            {
                CurrentImage = ListImage[position];
            }
        }