2017-01-16 3 views
0

gebunden werden Ich wollte ein Winform-Diagrammsteuerelement in ein WPF-Fenster einbetten, das an eine observablecollection gebunden werden soll, die durch Eingabe von Daten in einem WPF DataGrid ausgefüllt wird. Die observablecollection wird benötigt, weil ich sie mit einem WPF-DataGrid ausfülle, in dem ich Daten einfügen oder aktualisieren kann.Kann ein eingebettetes Winform-Diagramm an eine beobachtbare Sammlung in WPF

So fügte ich zu meinem WPF-Projekt der folgenden Abhängigkeiten: - System.Windows.Forms - System.Windows.Forms.DataVisualization

Für einen ersten Test i im Konstruktor der WPF-Fenster fest einprogrammiert einig Daten in der ObservableCollection und gebunden die Diagrammsteuerung. In diesem Fall funktioniert die Anzeige im Diagramm gut.

Aber in der endgültigen Version möchte ich Daten in das DataGrid einfügen und/oder aktualisieren und das Diagramm soll diese Daten auf einmal anzeigen. Ist das möglich?

Hier ist der Code für das Fenster und die Klassen als Beispiel.

Das WPF-Fenster 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> 

Der Code-behind von 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(); 
     } 

    } 
} 

Das 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)); 
     } 

    } 
} 

Und schließlich die Klasse StepData die ist die Basis für die beobachtbare Sammlung:

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

Ich denke, es sollte genauso funktionieren, wie Sie 'ChartDataRefresh' auf' grd_stepdata_RowEditEnding' aufrufen. Was ist das Problem, das Sie haben? – Pikoh

+0

Das Problem ist, dass, wenn ich die Methode "ChartDataRefresh" nur während des Button-Klick-Ereignisses das Diagramm nicht aktualisieren. Was ich sehe, ist ein weißer Adler auf einem weißen Hintergrund. –

Antwort

0

Ich habe es! Das Diagramm muss im Code-Behind erzeugt werden, nicht im XAML.

So ist die Methode ChartDataRefresh wie das auszusehen hat:

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; 
} 

Während Daten in der WPF-Datagrid das Winform Diagrammsteuer Eingabe aktualisiert wird und die Daten als Linie angezeigt zu überprüfen, ob die angegebenen Daten korrekt sind .

Verwandte Themen