Acessing Slider Value inside ContextMenu

Viewed 320

Im drawing a ContextMenuwith a slider inside.

This is my actual code:

<MenuItem  x:Name="menuSliderOpacity" Header="Opacidade" Width="100">
    <MenuItem.Template>
        <ControlTemplate TargetType="{x:Type MenuItem}">
            <Slider Width="100" 
                    Name="sliderOpacity" 
                    Minimum="0" 
                    Maximum="1" 
                    TickFrequency="0.1" 
                    IsSnapToTickEnabled="True"
                    ValueChanged="Slider_ChangeOpacity"
                    Value="{Binding ElementName=btnBackground, Path=Opacity, Mode=TwoWay}"/>
        </ControlTemplate>
    </MenuItem.Template>
</MenuItem>

For now that is my informations inside it. This slider will control the opacity of background of something on screen, like a button, for example. First I tried:

On the button

{Binding ElementName=sliderOpacity, Path=Value}

Or something like my Value on Slider with two way mode. How can I make that association? And after how could I get or set the value of slider on codebehind.

What is the correct way?

2 Answers

You can do this in different ways.

You can use binding like you already did in your XAML code.

This could be the code for your button:

<Button x:Name="btnBackgroundCodeBehind" Content="Code Behind Button" />

and this the XAML code for your menu:

<Menu Grid.Column="2">
    <MenuItem x:Name="menuSliderOpacity" Header="Opacidade" Width="100">
        <MenuItem.Template>
            <ControlTemplate TargetType="{x:Type MenuItem}">
                <Slider Width="100" 
                x:Name="sliderOpacity" 
                Minimum="0" 
                Maximum="1" 
                TickFrequency="0.1" 
                IsSnapToTickEnabled="True"
                ValueChanged="Slider_ChangeOpacity"
                Value="{Binding ElementName=btnBackground, Path=Opacity, Mode=OneWayToSource}"/>
          </ControlTemplate>
    </MenuItem.Template>
</MenuItem>

You do (almost) the same in code behind. Your method Slider_ChangeOpacity could look like this:

private void Slider_ChangeOpacity(object sender, RoutedPropertyChangedEventArgs<double> e)
{
    btnBackgroundCodeBehind.Opacity = e.NewValue;
}

I said almost because this is only a single way solution, it is only from slider to button.

If you would use an MVVM structure you could bind to the view model.

Whats the best way to do is up to your situation. If you create a complex program I would prefere binding to a view model. Shall you'd like to create only a view for your future use than I would prefere the direct binding. In case you have to do more complex manipulation with the data ammong the pair (button and slider) should use code behind.

Hope this answers your questions.

My solution was:

                <MenuItem Width="120" x:Name="menuSlider">
                    <MenuItem.Template>
                        <ControlTemplate TargetType="{x:Type MenuItem}">
                            <Grid>
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="auto"/>
                                    <RowDefinition Height="auto"/>
                                </Grid.RowDefinitions>
                                <Label Grid.Row="0">Opacidade</Label>
                                <Slider 
                                    Grid.Row="1"
                                    Margin="5,5,5,5"
                                    Width="100" 
                                    Name="sliderOpacity" 
                                    Minimum="0" 
                                    Maximum="1" 
                                    TickFrequency="0.1" 
                                    IsSnapToTickEnabled="True"
                                    Value="{Binding OpacityBackground,Mode=TwoWay}"/>
                            </Grid>
                        </ControlTemplate>
                    </MenuItem.Template>
                </MenuItem>

Ok, I didn't knew how to use Binding correctly, so I tried to avoid that. Just with this code i did what I wanted

    public double OpacityBackground
    {
        get { return btnBackground.Opacity; }
        set
        {
            btnBackground.Opacity = value;
            OnPropertyChanged("OpacityBackground");

            OnPanelChangeData?.Invoke(this, new OnPanelChangeArgs()
            {
                Value = btnBackground.Opacity.ToString(),
                Type = OnChangeType.Opacity
            });
        }
    }

    // Create the OnPropertyChanged method to raise the event
    protected void OnPropertyChanged(string name)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }
Related