我想在WPF窗口中嵌入一个winform图表控件,该窗口应绑定到通过在WPF DataGrid中输入数据填充的observablecollection。 需要observablecollection,因为我使用WPF-DataGrid填充它,我可以在其中插入或更新数据。
所以我在WPF项目中添加了以下依赖项: - System.Windows.Forms - System.Windows.Forms.DataVisualization
对于第一个测试,我在WPF窗口的构造函数中硬编码了observablecollection中的一些数据并绑定了图表控件。 在这种情况下,图表中的显示工作正常。
但在最终版本中,我想在DataGrid中插入和/或更新数据,图表将同时显示该数据。 有可能管理吗?
以下是窗口和类的代码示例。
WPF窗口MainWindow.xaml:
<Window x:Class="StepFunctions.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:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
xmlns:winformchart="clr-namespace:System.Windows.Forms.DataVisualization.Charting;assembly=System.Windows.Forms.DataVisualization"
xmlns:local="clr-namespace:StepFunctions"
mc:Ignorable="d"
Title="StepFunctions"
Height="350"
Width="525">
<Grid x:Name="maingrid">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!--DataGrid for insert and update of step function data-->
<DataGrid x:Name="grd_stepdata"
Grid.Row="0"
Grid.Column="0"
Margin="5"
AutoGenerateColumns="False"
CanUserAddRows="True"
RowEditEnding="grd_stepdata_RowEditEnding"
ItemsSource="{Binding StepDataSource, NotifyOnSourceUpdated=True, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<DataGrid.Columns>
<DataGridTextColumn x:Name="col_LowerComparer" Binding="{Binding LowerComparer, NotifyOnTargetUpdated=True, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Header="Lower comparer"/>
<DataGridTextColumn x:Name="col_LowerBound" Binding="{Binding LowerBound, NotifyOnTargetUpdated=True, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Header="Lower bound"/>
<DataGridTextColumn x:Name="col_StepValue" Binding="{Binding StepValue, NotifyOnTargetUpdated=True, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Header="Value"/>
</DataGrid.Columns>
</DataGrid>
<!--Chart for displaying the step function data-->
<WindowsFormsHost x:Name="host"
Grid.Row="0"
Grid.Column="1"
Margin="5">
<winformchart:Chart x:Name="myWinformChart"
Dock="Fill">
<winformchart:Chart.Series>
<winformchart:Series Name="series" ChartType="Line"/>
</winformchart:Chart.Series>
<winformchart:Chart.ChartAreas>
<winformchart:ChartArea/>
</winformchart:Chart.ChartAreas>
</winformchart:Chart>
</WindowsFormsHost>
<!--Button for test-->
<Button x:Name="btn_do"
Grid.Row="2"
Grid.Column="0"
Margin="5"
Click="btn_do_Click">Do it</Button>
</Grid>
</Window>
MainWindow.xaml的代码隐藏:
using StepFunctions.ViewModels;
using System.Windows;
using System.Windows.Controls;
namespace StepFunctions
{
/// <summary>
/// Interaktionslogik für MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private MainWindowViewModel vm = new MainWindowViewModel();
public MainWindow()
{
InitializeComponent();
DataContext = vm;
// These lines are just for the first test.
// Normally these lines would be out-commented.
AddStepdata();
ChartDataRefresh();
}
// When the user leaves a DataGrid-row after insert or update the chart shall be refreshed.
private void grd_stepdata_RowEditEnding(object sender, DataGridRowEditEndingEventArgs e)
{
ChartDataRefresh();
}
private void AddStepdata()
{
vm.StepDataSource.Add(new StepData("<", 10, 1));
vm.StepDataSource.Add(new StepData("<", 100, 2));
vm.StepDataSource.Add(new StepData("<", 1000, 3));
}
private void ChartDataRefresh()
{
myWinformChart.DataSource = vm.StepDataSource;
myWinformChart.Series["series"].XValueMember = "LowerBound";
myWinformChart.Series["series"].YValueMembers = "StepValue";
}
/// <summary>
/// For testing the refresh of the chart after the window was loaded.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btn_do_Click(object sender, RoutedEventArgs e)
{
AddStepdata();
ChartDataRefresh();
}
}
}
viewmodel:
using System.Collections.ObjectModel;
using System.ComponentModel;
namespace StepFunctions.ViewModels
{
public class MainWindowViewModel : INotifyPropertyChanged
{
/// <summary>
/// Eventhandler for signalising that a property has changed.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
private ObservableCollection<StepData> stepdataSource = new ObservableCollection<StepData>();
public ObservableCollection<StepData> StepDataSource
{
get { return stepdataSource; }
set
{
stepdataSource = value;
RaisePropertyChanged("StepDataSource");
}
}
/// <summary>
/// Informs the target which is bound to a property, that it's source was changed and that it shall update.
/// </summary>
/// <param name="propertyName">The name of the property.</param>
public void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
最后是类StepData,它是observablecollection的基础:
namespace StepFunctions.ViewModels
{
/// <summary>
/// Class for data of stepfunctions.
/// </summary>
public class StepData
{
/// <summary>
/// The constructor.
/// </summary>
public StepData()
{
// Do nothing
}
public StepData(string lowerComparer, double lowerBound, double stepValue)
{
LowerComparer = lowerComparer;
LowerBound = lowerBound;
StepValue = stepValue;
}
public string LowerComparer { get; set; }
public double LowerBound { get; set; }
public double StepValue { get; set; }
}
}
答案 0 :(得分:0)
我明白了! 图表必须在代码隐藏中生成,而不是在XAML中生成。
因此ChartDataRefresh方法必须如此:
private void ChartDataRefresh()
{
Chart myWinformChart = new Chart();
myWinformChart.Dock = System.Windows.Forms.DockStyle.Fill;
Series mySeries = new Series("series");
mySeries.ChartType = SeriesChartType.Line;
myWinformChart.Series.Add(mySeries);
ChartArea myArea = new ChartArea();
myWinformChart.ChartAreas.Add(myArea);
myWinformChart.DataSource = vm.StepDataSource;
myWinformChart.Series["series"].XValueMember = "LowerBound";
myWinformChart.Series["series"].YValueMembers = "StepValue";
host.Child = myWinformChart;
}
在WPF-DataGrid中输入数据时,将刷新Winform图表控件,并将数据显示为一行,以检查给定数据是否正确。