WPF MVVM에서 ScottPlot을 사용하고 있는데요.

Caliburn.micro를 사용해서 MVVM구조로 모니터링 프로그램을 짜고 있는데요.

데이터를 Plot을 할려고 하다보니 Scottplot이라는 OpenSource를 사용하려고 하는데,

얘 구조가 MVVM를 지원하지 않는 구조로 되어 있더군요(성능을 위해서라는데)

구글링을 통해서 wrapping 해서 MVVM처럼 구현해서 쓰고 있는데요.

ScottPlot 버전을 업데이트 할때마다 뭔가 구조가 바꼈는지 코드를 수정해야 제대로 보여지더군요.

그래서 그냥 ScottPlot에서 추천하는? 방식으로 코드 비하인드로 Plot부분만 수정할려고 하는데,

다른 뷰모델에서 Plot 뷰의 비하인드에 데이터를 전달하도록 할려고 하니 감이 안옵니다.

방법이 있을까요?.

2개의 좋아요

뷰모델에서 뷰로 데이터를 전달하는 인터페이스를 만들고 그 인터페이스를 통해 뷰 코드에서 Scottplot의 데이터를 업데이트 하면 되지 않나요?

2개의 좋아요

이 부분은 라이브러리를 사용하는 입장에서 당연히 나타날 수 있는 문제이기 때문에 감안하셔야 합니다.
이러한 문제 때문에 일부 회사에서는 프로젝트 진행하는 동안 라이브러리 버전을 고정해서 사용합니다.

제가 간단하게 확인해봤는데 WpfPlot을 하위속성으로 갖는 UserControl을 만들면 가장 쉽고 간단할 것 같아보여요.
뷰모델에서 뷰에 접근하는 방식이면 나중 유지보수가 어마어마하게 어려워 질 수 있기 때문입니다.

<!-- MyPlot.xaml -->
<UserControl x:Class="Scottplot_WPF.MyPlot"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:local="clr-namespace:Scottplot_WPF"
             mc:Ignorable="d"
             d:DesignHeight="450" d:DesignWidth="800">
    <WpfPlot x:Name="PlotView"/>
</UserControl>
// MyPlot.xaml.cs

public partial class MyPlot : UserControl
{
    public static readonly DependencyProperty ScattersProperty = DependencyProperty.Register(
        nameof(Scatters), typeof(ICollection<Scatter>), typeof(MyPlot), new FrameworkPropertyMetadata(OnScattersChanged));

    public ICollection<Scatter>? Scatters
    {
        get => GetValue(ScattersProperty) as ICollection<Scatter>;
        set => SetValue(ScattersProperty, value);
    }

    public MyPlot()
    {
        InitializeComponent();
    }

    private static void OnScattersChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (d is not MyPlot myPlot)
            return;

        if (e.NewValue is not ICollection<Scatter> scatters)
            return;

        myPlot.PlotView.Plot.Clear();

        foreach (var scatter in scatters)
        {
            myPlot.PlotView.Plot.AddScatter(scatter.XDatas, scatter.YDatas);
        }

        myPlot.PlotView.Refresh();
    }
}
<!-- MyPlot를 사용하려는 곳에서 -->
...
<local:MyPlot Scatters="{Binding Scatters}"/>
...
// MyPlot를 사용하려는 곳의 ViewModel
...
// 만약 속성이 변할 수 있으면 ICollection 대신 ObservableCollection이나 BindingList
public ICollection<Scatter> Scatters { get; set; }
...

여기서 나온 Scatter는 제가 임시로 만든 자료구조인데 사용환경에 맞게 작성하면 될 것 같아요.

파일을 압축해서 올리려 했는데 업로드 제한에 걸리네요… :thinking:

public readonly struct Scatter
{
    public double[] XDatas { get; }
    public double[] YDatas { get; }

    public Scatter(double[] xDatas, double[] yDatas)
    {
        XDatas = xDatas;
        YDatas = yDatas;
    }
}
5개의 좋아요

감사합니다. 덕분에 해결되었네요.
MVVM구조에 생각이 종속되다 보니 감이 안왔는데, 감이 딱 오네요.^^

1개의 좋아요