none
WindowsFormsHost + Chart. Отрисовка за пределами UserControl в WPF. Ошибка? RRS feed

  • Общие обсуждения

  • Здравствуйте.

    Имеется задача: необходимо отрисовать несколько графиков в списке с прокруткой.

    Для отрисовк графика используется Cart из Windows.Forms

    График имеет дополнительное описание.

    График с описание помещается в UserControl (WPF).

    Набор таких элементов помещается в Grid или StackPanel или StackPanel

    Заполнив элемент графиками, наблюдается следующий эффект (Ошибка?):

    Все элементы Chart выходят за пределы UserControl, внутрь которого они помещены, при использовании прокрутки ScrollViewer или аналога.

    Можно ли как-то убрать данный эффект?

    Синтетический пример кода ниже

    Основное окно XAML

    <Window x:Class="Test_WF_WPF.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:Test_WF_WPF"
            mc:Ignorable="d"
            Title="MainWindow" Height="350" Width="525">
        <Grid Name="mainGrid">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition/>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
            <StackPanel Grid.Row="0">
                <TextBlock Text="Текст ВВЕРХУ" Height="20"/>
                <Button Content="Отрисовать GRID" Click="Button_Click_1"/>
                <Button Content="Отрисовать STACK" Click="Button_Click_2"/>
                <Button Content="Отрисовать LISTVIEW" Click="Button_Click_3"/>
            </StackPanel>
            <StackPanel Grid.Row="2">
                <TextBlock Text="Текст ВНИЗУ" Height="100"/>
            </StackPanel>
        </Grid>
    </Window>
    

    Код основного окна

    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.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    
    namespace Test_WF_WPF
    {
        /// <summary>
        /// Логика взаимодействия для MainWindow.xaml
        /// </summary>
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
            }
    
            private void Button_Click_1(object sender, RoutedEventArgs e)
            {
                var rnd = new Random();
                List<List<double>> listOfList = new List<List<double>>();
                for(int i=0;i<10;i++)
                {
                    List<double> list = new List<double>();
                    listOfList.Add(list);
                    for (int j = 0; j < 10; j++)
                        list.Add(1+rnd.NextDouble());
                }
                ListPlot1 ctr = new ListPlot1();
                ctr.Set(listOfList);
                Grid.SetRow(ctr, 1);
                mainGrid.Children.Add(ctr);
    
            }
    
            private void Button_Click_2(object sender, RoutedEventArgs e)
            {
                var rnd = new Random();
                List<List<double>> listOfList = new List<List<double>>();
                for (int i = 0; i < 10; i++)
                {
                    List<double> list = new List<double>();
                    listOfList.Add(list);
                    for (int j = 0; j < 10; j++)
                        list.Add(1 + rnd.NextDouble());
                }
                ListPlot2 ctr = new ListPlot2();
                ctr.Set(listOfList);
                Grid.SetRow(ctr, 1);
                mainGrid.Children.Add(ctr);
            }
    
            private void Button_Click_3(object sender, RoutedEventArgs e)
            {
                var rnd = new Random();
                List<List<double>> listOfList = new List<List<double>>();
                for (int i = 0; i < 10; i++)
                {
                    List<double> list = new List<double>();
                    listOfList.Add(list);
                    for (int j = 0; j < 10; j++)
                        list.Add(1 + rnd.NextDouble());
                }
                ListPlot3 ctr = new ListPlot3();
                ctr.Set(listOfList);
                Grid.SetRow(ctr, 1);
                mainGrid.Children.Add(ctr);
            }
        }
    }
    

    Обертка для прикрепления Chart в WPF. Код XAML

    <UserControl x:Class="Test_WF_WPF.wfWrapp"
                 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:Test_WF_WPF"
                 mc:Ignorable="d" 
                 d:DesignHeight="300" d:DesignWidth="300">
        <Grid Name="mainGrid">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition/>
            </Grid.RowDefinitions>
            <StackPanel Grid.Row="0">
                <Label Content="Описание"/>
                <TextBox Name="myText"/>
            </StackPanel>
        </Grid>
    </UserControl>
    

    Обертка для прикрепления Chart в WPF. Код C#

    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.Data;
    using System.Windows.Documents;
    using System.Windows.Forms.DataVisualization.Charting;
    using System.Windows.Forms.Integration;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    
    namespace Test_WF_WPF
    {
        /// <summary>
        /// Логика взаимодействия для wfWrapp.xaml
        /// </summary>
        public partial class wfWrapp : UserControl
        {
            public wfWrapp()
            {
                InitializeComponent();
            }
    
            private Chart _chart;
            private WindowsFormsHost _host;
            private string _name = "plot";
    
            public Chart Chart
            {
                get
                {
                    return _chart;
                }
            }
    
            public WindowsFormsHost Host
            {
                get
                {
                    return _host;
                }
            }
    
            public void Set(List<double> points)
            {
                if (points == null || points.Count == 0) return;
                myText.Text = "Число точек " + points.Count.ToString();
    
                _chart = new Chart();
                _chart.Series.Add(_name);
                _chart.ChartAreas.Add(_name);
                _chart.Legends.Add(_name);
    
                _host = new WindowsFormsHost();
                _host.Child = _chart;
    
                System.Windows.Controls.Grid.SetRow(_host, 1);
                mainGrid.Children.Add(_host);
    
                var ser = _chart.Series[_name];
                int index = 0;
                foreach (var p in points)
                {
                    ser.Points.AddXY(index, p);
                    index++;
                }
            }
        }
        
    }
    

    Пример добавления в Grid с ScrollViewer. Код XAML

    <UserControl x:Class="Test_WF_WPF.ListPlot1"
                 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:Test_WF_WPF"
                 mc:Ignorable="d" 
                 d:DesignHeight="300" d:DesignWidth="300">
        <ScrollViewer VerticalScrollBarVisibility="Visible" Name="mainScroll">
        <Grid Name="mainGrid">
                
        </Grid>
        </ScrollViewer>
    </UserControl>
    

    Пример добавления в Grid с ScrollViewer. Код C#

    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.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    
    namespace Test_WF_WPF
    {
        /// <summary>
        /// Логика взаимодействия для ListPlots.xaml
        /// </summary>
        public partial class ListPlot1 : UserControl
        {
            public ListPlot1()
            {
                InitializeComponent();
            }
    
            private Dictionary<List<double>, wfWrapp> _dic = null;
    
            public void Set(List<List<double>> listOflist)
            {
                _dic = new Dictionary<List<double>, wfWrapp>();
                int index = 0;
                foreach(var list in listOflist)
                {
                    if (list == null || list.Count == 0) continue;
                    _dic.Add(list, new wfWrapp());
                    wfWrapp wfItem = _dic[list];
                    wfItem.Set(list);
                    mainGrid.RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto });
                    Grid.SetRow(wfItem, index);
                    mainGrid.Children.Add(wfItem);
                    index++;
                }
            }
        }
    }
    

    Пример добавления в StackPanel. Код XAML

    <UserControl x:Class="Test_WF_WPF.ListPlot2"
                 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:Test_WF_WPF"
                 mc:Ignorable="d" 
                 d:DesignHeight="300" d:DesignWidth="300">
        <ScrollViewer VerticalScrollBarVisibility="Visible" Name="mainScroll">
            <StackPanel Name="mainStack" Orientation="Vertical">
                <ListView/>
            </StackPanel>
        </ScrollViewer>
    </UserControl>
    

    Пример добавления в StackPanel. Код C#

    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.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    
    namespace Test_WF_WPF
    {
        /// <summary>
        /// Логика взаимодействия для ListPlot2.xaml
        /// </summary>
        public partial class ListPlot2 : UserControl
        {
            public ListPlot2()
            {
                InitializeComponent();
            }
    
            private Dictionary<List<double>, wfWrapp> _dic = null;
    
            public void Set(List<List<double>> listOflist)
            {
                _dic = new Dictionary<List<double>, wfWrapp>();
                int index = 0;
                foreach (var list in listOflist)
                {
                    if (list == null || list.Count == 0) continue;
                    _dic.Add(list, new wfWrapp());
                    wfWrapp wfItem = _dic[list];
                    wfItem.Set(list);
                    mainStack.Children.Add(wfItem);
                    index++;
                }
            }
        }
    }
    

    Пример добавления в ListView. Код XAML

    <UserControl x:Class="Test_WF_WPF.ListPlot3"
                 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:Test_WF_WPF"
                 mc:Ignorable="d" 
                 d:DesignHeight="300" d:DesignWidth="300">
        <ListView Name="mainListView" >
            
        </ListView>
    </UserControl>
    

    Пример добавления в ListView. Код C#

    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.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    
    namespace Test_WF_WPF
    {
        /// <summary>
        /// Логика взаимодействия для ListPlot3.xaml
        /// </summary>
        public partial class ListPlot3 : UserControl
        {
            public ListPlot3()
            {
                InitializeComponent();
            }
    
            private Dictionary<List<double>, wfWrapp> _dic = null;
    
            public void Set(List<List<double>> listOflist)
            {
                _dic = new Dictionary<List<double>, wfWrapp>();
                int index = 0;
                foreach (var list in listOflist)
                {
                    if (list == null || list.Count == 0) continue;
                    _dic.Add(list, new wfWrapp());
                    wfWrapp wfItem = _dic[list];
                    wfItem.Set(list);
                    mainListView.Items.Add(wfItem);
                    index++;
                }
            }
        }
    }
    

    При проктурик элемента с графиками, Chart не обрезаются за границами UserControl

    22 ноября 2016 г. 20:33