1 year ago

#70361

test-img

Anno

How to set a DependenceProperty if another DependencyProperty changes?

This is my solution structure:

solution structure

My MainWindow.xaml:

<Window x:Class="ExampleApp.Views.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:paretoPlot="clr-namespace:ParetoPlotCustomControl;assembly=ParetoPlotCustomControl"
        xmlns:prism="http://prismlibrary.com/"
        prism:ViewModelLocator.AutoWireViewModel="True" Height="350" Width="525">
    <Grid>
        <StackPanel>
            <Button Command="{Binding CreateNewParetoCommand}" Height="50" Width="100">Create Pareto</Button>
            <paretoPlot:ParetoPlotControl Width="Auto" Height="300" ParetoData="{Binding CustomParetoData}"/>
        </StackPanel>
    </Grid>
</Window>

My MainWindowViewModel.cs:

using System.Collections.Generic;
using MathNet.Spatial.Euclidean;
using OxyPlot;
using Pareto;
using Prism.Commands;
using Prism.Mvvm;

namespace ExampleApp.ViewModels
{
    public class MainWindowViewModel : BindableBase
    {
        private Pareto.Pareto _customParetoData;
        public Pareto.Pareto CustomParetoData
        {
            get { return _customParetoData; }
            set { SetProperty(ref _customParetoData, value); }
        }

        private DelegateCommand _createNewParetoCommand;
        public DelegateCommand CreateNewParetoCommand =>
            _createNewParetoCommand ?? (_createNewParetoCommand = new DelegateCommand(ExecuteCreateNewParetoCommand));

        void ExecuteCreateNewParetoCommand() => CustomParetoData = CreateARandomPareto();

        public MainWindowViewModel()
        {
            //CustomParetoData = CreateARandomPareto();
        }

        private Pareto.Pareto CreateARandomPareto()
        {
            var pareto = // Irrelevant code.
            return pareto;
        }
    }
}

My ParetoPlotControl.cs:

public class ParetoPlotControl : Control
    {
        public Pareto.Pareto ParetoData
        {
            get => (Pareto.Pareto)GetValue(ParetoDataProperty);
            set { UpdateParetoPlot(); SetValue(ParetoDataProperty, value); }
        }

        public static readonly DependencyProperty ParetoDataProperty =
            DependencyProperty.Register("ParetoData", typeof(Pareto.Pareto),
                typeof(ParetoPlotControl),
                new PropertyMetadata(new Pareto()));

        internal PlotModel OxyPlotModel
        {
            get { return (PlotModel)GetValue(OxyPlotModelProperty); }
            private set { SetValue(OxyPlotModelProperty, value); }
        }

        public static readonly DependencyProperty OxyPlotModelProperty =
            DependencyProperty.Register("OxyPlotModel", typeof(PlotModel),
                typeof(ParetoPlotControl), new PropertyMetadata(new PlotModel{Title = "Pareto Plot"}));

        static ParetoPlotControl()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(ParetoPlotControl),
                new FrameworkPropertyMetadata(typeof(ParetoPlotControl)));
        }

        private void UpdateParetoPlot()
        {
            OxyPlotModel.Series.Clear();
            OxyPlotModel.Axes.Clear();
            OxyPlotModel.Axes.Add(new LinearAxis{Position = AxisPosition.Bottom, Title = "1 - TCP"});
            OxyPlotModel.Axes.Add(new LinearAxis{Position = AxisPosition.Left, Title = "NTCP"});
            var paretoPointSeries = GetParetoPointSeries() // Irrelevant here.;
            foreach (var series in paretoPointSeries) OxyPlotModel.Series.Add(series);
            OxyPlotModel.InvalidatePlot(true);
        }
    }

and my Generic.xaml:

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:ParetoPlotCustomControl"
    xmlns:oxy="http://oxyplot.org/wpf">
    <Style TargetType="{x:Type local:ParetoPlotControl}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:ParetoPlotControl}" >
                    <Grid>
                        <oxy:PlotView Model="{TemplateBinding OxyPlotModel}"/>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

What I would like to happen is that:

  1. MainWindowViewModel has only access to the ParetoData property, but not to OxyPlotModel.
  2. When MainWindowViewModel changes the Pareto, the OxyPlotModel shall be updated with the new Pareto.

Problem is that the UpdatePareoPlot() is never executed. How can I achieve this?

I tried using a PropertyChangedCallback for ParetoDataProperty, but then I cannot access OxyPlotModel, because it is not static. If I turn OxyPlotModel to a normal property instead of DependencyProperty, I cannot bind it to Generic.xaml...

c#

wpf

custom-controls

dependency-properties

0 Answers

Your Answer

Accepted video resources