对于我的项目,我正在尝试创建一个连接到工具集并将信号推送到其中的信号通道生成器。
我遇到的问题是,我以文本框代码位于代码隐藏文件中的形式获得了项目,并且我希望它们位于 xaml 中。
我有一个变量来控制可以更改的通道数(视图模型)。它能够在窗口上创建同一视图模型的多个实例。这允许在工具内选择与之通信的不同目标,并能够将信号泵送到每个目标。
这是当前在 XAML 中的代码:
<Window x:Class="SigGeneratorMVVM.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SigGeneratorMVVM"
Title="Signal Generator" Height="370" Width="734" >
<StackPanel Name="MyWindow">
<!--<TextBox Height="23" HorizontalAlignment="Left" Margin="91,20,0,0" Name="CurrentValDisplay" VerticalAlignment="Top" Width="120" />-->
</StackPanel>
</Window>
这是 mainwindow.cs 的代码
public partial class MainWindow : Window
{
List<ViewModel> gViewModels;
int gNumChannels = 1;
private System.Threading.Timer mViewUpdateTimer;
private TimerCallback mViewTimerCallback;
private UtilityParticipant mParticipant;
public MainWindow()
{
InitializeComponent();
// Connect as UtilityParticipant
ConnectMesh();
gViewModels = new List<ViewModel>();
for (int i = 0; i < gNumChannels; i++)
{
gViewModels.Add(new ViewModel(mParticipant));
TextBlock CurrentValueText = new TextBlock();
CurrentValueText.Text = "Current Value:";
CurrentValueText.Margin = new Thickness(5);
TextBox CurrentValueBox = new TextBox();
CurrentValueBox.Width = 120;
CurrentValueBox.Name = "CurrentValDisplay" + i.ToString();
CurrentValueBox.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
CurrentValueBox.Margin = new Thickness(10);
CurrentValueBox.SetBinding(TextBox.TextProperty, "CurrentValue");
//CurrentValDisplay.Name = "CurrentValDisplay" + i.ToString();
//CurrentValDisplay.SetBinding(TextBox.TextProperty, "CurrentValue");
TextBlock CurrentFrequencyText = new TextBlock();
CurrentFrequencyText.Text = "Frequency:";
CurrentFrequencyText.Margin = new Thickness(5);
TextBox CurrentFrequencyBox = new TextBox();
CurrentFrequencyBox.Width = 120;
CurrentFrequencyBox.Name = "CurrentFrequencyDisplay" + i.ToString();
CurrentFrequencyBox.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
CurrentFrequencyBox.Margin = new Thickness(10);
CurrentFrequencyBox.SetBinding(TextBox.TextProperty, "Frequency");
Slider FrequencySlider = new Slider();
FrequencySlider.Width = 200;
FrequencySlider.Name = "FrequencySet" + i.ToString();
FrequencySlider.Value= 10;
FrequencySlider.Maximum = 10;
FrequencySlider.Minimum = 0.1;
FrequencySlider.SetBinding(Slider.ValueProperty, "Frequency");
//Create a new stackpanel
StackPanel sp = new StackPanel();
sp.Orientation = Orientation.Vertical;
//Set DataContext of the StackPanel
sp.DataContext = gViewModels[i];
//Add controls created above to the StackPanel
sp.Children.Add(CurrentValueText);
sp.Children.Add(CurrentValueBox);
sp.Children.Add(CurrentFrequencyText);
sp.Children.Add(CurrentFrequencyBox);
sp.Children.Add(FrequencySlider);
//Add the StackPanel to the window
MyWindow.Children.Add(sp);
}
mViewTimerCallback = this.UpdateView;
mViewUpdateTimer = new System.Threading.Timer(mViewTimerCallback, null, 100, 20);
}
更新:我已经有一个 ViewModel,它为每个属性(现在是 CurrentValue 和 Frequency)设置了方法,将 DataTemplate 和 ItemsControl 绑定到它而不是创建一个新的模型类就足够了吗?
private SigGenChannel mSigGenChannel;
//Constructor
public ViewModel(UtilityParticipant aParticipant)
{
mSigGenChannel = new SigGenChannel(aParticipant);
}
public string CurrentValue
{
get
{
return mSigGenChannel.CurrentValue.ToString();
}
set
{
mSigGenChannel.CurrentValue = double.Parse(value);
RaisePropertyChanged("CurrentValue");
}
}
public double Frequency
{
get
{
return mSigGenChannel.Frequency;
}
set
{
mSigGenChannel.Frequency = value;
RaisePropertyChanged("Frequency");
}
}
public double Amplitude
{
get
{
return mSigGenChannel.Amplitude;
}
set
{
mSigGenChannel.Amplitude = value;
RaisePropertyChanged("Amplitude");
}
}
public void RefreshValue()
{
//A bit of a cheat, but we provide a means to poke the Viewmodel
//And raise a property change event
RaisePropertyChanged("CurrentValue");
}
这也是 SigChannel 模型:
class SigGenChannel
{
#region Private members
private UtilityParticipant mParticipant;
private double mCurrentValue;
private double mFrequency;
private double mAmplitude;
private double mTarget;
private double mOffset;
private double mCurrentStepTime;
private DateTime mStartTime;
private System.Threading.Timer mTimer;
private TimerCallback mTCallback;
private int mUpdateInterval = 10;
#endregion
#region Public members
public double CurrentValue
{
get
{
return mCurrentValue;
}
set
{
mCurrentValue = value;
}
}
public double Frequency
{
get
{
return mFrequency;
}
set
{
mFrequency = value;
}
}
public double Amplitude
{
get
{
return mAmplitude;
}
set
{
mAmplitude = value;
}
}
public double Target
{
get
{
return mTarget;
}
set
{
mTarget = value;
}
}
#endregion
//Constructor
public SigGenChannel(UtilityParticipant aParticipant)
{
mParticipant = aParticipant;
mCurrentValue = 10;
mFrequency = 200;
mAmplitude = 100;
mOffset = 0;
mCurrentStepTime = 0;
mStartTime = DateTime.Now;
mTCallback = this.Update;
mTimer = new System.Threading.Timer(mTCallback, null, 500, mUpdateInterval);
//Array enumData = Enum.GetNames;
//RefreshItems();
//Temp Code....!
Collection lCollection = mParticipant.GetCollection("DefaultNodeName.NodeStats");
lCollection.Publish();
}
private void Update(object StateInfo)
{
TimeSpan span = DateTime.Now - mStartTime;
mCurrentStepTime = span.TotalMilliseconds / (double)1000;
mCurrentValue = (Math.Sin(mCurrentStepTime * (mFrequency * 2 * Math.PI)) * mAmplitude / 2) + mOffset;
//Temp Code...!
Collection lCollection = mParticipant.GetCollection("DefaultNodeName.NodeStats");
Parameter lParameter = lCollection.GetParameter("CPUPercent");
lParameter.SetValue(mCurrentValue);
lCollection.Send();