我的项目中有两个窗口(MainWindow和一个小窗口,用于MainWindow控件的某些属性)。在MainWindow的一个Tab中,有一个Grid分为十列。在每个列中都有一些控件。下面是我的项目的示例代码。
如果我将Label(MainWindow)中的Period(CheckBox)检查为“Period”,并且当我检查频率(PropertiesWindow中的CheckBox)时Label(MainWindow)为“Frequency”,我想要。
当我选中PropertiesWindow(Period或Frequency)中的一个复选框时,我希望MainWindow上的Label(lb_freq1)根据选中的CheckBox的内容更改其内容。 (此外,所选单位要在time_div1(标签)处显示)。
第一个解决方案:
XAML MainWindow:
<Window x:Class="wpf1.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-wpf1"
mc:Ignorable="d"
Title="wpf1" Height="720" Width="1280" WindowStartupLocation="CenterScreen" Icon="kkk.bmp" Background="#FFE0E0E0" Foreground="#FF49A81D" BorderBrush="#FFB93838" >
<Grid>
<TabControl x:Name="tabControl">
<TabItem Header="Tab1">
<Grid>
<StackPanel>
<Label x:Name="lb_freq1" Content="Period" HorizontalAlignment="Center" Margin="0,10,0,0" />
<StackPanel Orientation="Horizontal" Margin="0" HorizontalAlignment="Center">
<TextBox x:Name="txt_freq1" Width="50" Height="20" HorizontalContentAlignment="Right" BorderThickness="1,1,0,1" HorizontalAlignment="Left" VerticalContentAlignment="Center"/>
<Label x:Name="time_div1" Content="us" Width="20" BorderThickness="0,1,1,1" Margin="0" HorizontalAlignment="Right" Height="20" Padding="0" BorderBrush="#FFABADB3" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" />
</StackPanel>
<Label x:Name="lb_width1" Content="Pulse Width" HorizontalAlignment="Center" Margin="0,10,0,0" />
<StackPanel Orientation="Horizontal" Margin="0" HorizontalAlignment="Center">
<TextBox x:Name="txt_width1" Width="50" Height="20" HorizontalContentAlignment="Right" BorderThickness="1,1,0,1" HorizontalAlignment="Left"/>
<Label x:Name="pv_div1" Content="us" Width="20" BorderThickness="0,1,1,1" Margin="0" HorizontalAlignment="Right" Height="20" Padding="0" BorderBrush="#FFABADB3" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" />
</StackPanel>
<Button x:Name="Properties1" Content="Properties" Margin="10,30,10,10" HorizontalAlignment="Center" BorderBrush="Blue" Click="Properties1_Click" />
</StackPanel>
</Grid>
</TabItem>
</TabControl>
</Grid>
</Window>
EDITED MainWindow背后的代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Threading.Tasks;
using System.Threading;
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;
using System.Globalization;
using System.ComponentModel;
namespace wpf1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
ViewModel viewModel = new ViewModel();
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
}
private void Properties1_Click(object sender, RoutedEventArgs e)
{
string res1 = lb_freq1.Content.ToString();
string res3 = time_div1.Content.ToString();
var newWindow = new PWMProperties();
newWindow.Owner = this;
newWindow.ShowDialog();
string result1 = newWindow.Value1;
if (result1 == null)
{
lb_freq1.Content = res1;
}
else
{
lb_freq1.Content = result1;
}
string result3 = newWindow.Unit1;
if (result3 == null)
{
time_div1.Content = res3;
}
else
{
time_div1.Content = result3;
}
}
}
}
XAML PropertiesWindow:
<Window x:Class="wpf1.PWMProperties"
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:wpf1"
mc:Ignorable="d"
Title="Properties" Height="335" Width="285" ResizeMode="NoResize" BorderThickness="0" WindowStartupLocation="CenterOwner">
<Window.Resources>
<local:BoolConverter2 x:Key="Converter"></local:BoolConverter2>
<local:BoolConverter x:Key="Reverse"></local:BoolConverter>
</Window.Resources>
<Grid>
<StackPanel VerticalAlignment="Top" Margin="0,10,0,0" HorizontalAlignment="Center">
<StackPanel Orientation="Horizontal" Margin="0,0,0,20">
<StackPanel Margin="0,0,49,0">
<RadioButton x:Name="SelectPeriod" Content="Period" Margin="0,0,0,0" Click="SelectPeriod_Click" />
<ComboBox x:Name="PeriodUnits" Padding="3,2,2,2" IsReadOnly="True" IsEditable="True" Text="us" IsEnabled="{Binding ElementName=SelectPeriod, Path=IsChecked}" SelectionChanged="PeriodUnits_SelectionChanged"
ItemsSource="{Binding PeriodComboBoxItems}">
</ComboBox>
</StackPanel>
<StackPanel Margin="20,0,0,0">
<RadioButton x:Name="SelectFrequency" Content="Frequency" Click="SelectFrequency_Click" />
<ComboBox x:Name="FrequencyUnits" Padding="3,2,2,2" IsReadOnly="True" IsEditable="True" Text="Hz" IsEnabled="{Binding ElementName=SelectFrequency, Path=IsChecked}" SelectionChanged="FrequencyUnits_SelectionChanged"
ItemsSource="{Binding FrequencyComboBoxItems}">
</ComboBox>
</StackPanel>
</StackPanel>
</StackPanel>
<StackPanel Orientation="Horizontal" VerticalAlignment="Bottom" Margin="0">
<Button x:Name="OkButton" Content="OK" Margin="135,5,10,5" Click="OkButton_Click" Width="60" />
<Button x:Name="CancelButton" Content="Cancel" Click="CancelButton_Click" Width="60" Margin="0,5,10,5" />
</StackPanel>
</Grid>
</Window>
EDITED PropertyWindow背后的代码:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
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.Shapes;
using System.ComponentModel;
using System.IO;
using System.Xml;
using System.Windows.Markup;
namespace wpf1
{
/// <summary>
/// Interaction logic for Analog.xaml
/// </summary>
public partial class PWMProperties : Window
{
public ObservableCollection<string> PeriodComboBoxItems { get; set; }
public ObservableCollection<string> FrequencyComboBoxItems { get; set; }
public ObservableCollection<string> PulseWidthComboBoxItems { get; set;}
public PWMProperties()
{
InitializeComponent();
this.DataContext = this;
this.PeriodComboBoxItems = new ObservableCollection<string>() { "us", "ms", "s" };
this.FrequencyComboBoxItems = new ObservableCollection<string>() { "Hz", "kHz", "MHz" };
this.PulseWidthComboBoxItems = new ObservableCollection<string>() { "us", "ms", "s" };
}
string val1, val2, unit1, unit2;
private void OkButton_Click(object sender, RoutedEventArgs e)
{
if (SelectPeriod.IsChecked == true)
{
val1 = "Period";
if (unit1 == null || unit1!="ms") unit1 = "us";
}
if (SelectFrequency.IsChecked == true)
{
val1 = "Frequency";
if (unit1 == null || unit1!="kHz") unit1 = "Hz";
}
DialogResult = true;
}
private void CancelButton_Click(object sender, RoutedEventArgs e)
{
DialogResult = false;
}
public string Value1 { get { return val1; } }
public string Value2 { get { return val2; } }
public string Unit1 { get { return unit1; } }
public string Unit2 { get { return unit2; } }
private void PeriodUnits_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
unit1 = PeriodUnits.SelectedItem.ToString();
}
private void FrequencyUnits_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
unit1 = FrequencyUnits.SelectedItem.ToString();
}
}
public class BoolConverter2 : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
bool v = (bool)value;
return v;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new System.NotSupportedException();
}
}
}
第二种可能的解决方案:
然后,我在我的MainWindow代码中添加了一个ViewModel:
public class ViewModel : INotifyPropertyChanged
{
private string _value1 = "Period";
public event PropertyChangedEventHandler PropertyChanged;
public string Value1
{
get { return _value1; }
set
{
_value1 = value;
OnPropertyChanged("Value1");
}
}
protected virtual void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
因此,删除了PropertiesWindow背后的大部分代码,并在MainWindow中使用Binding来更改lb_freq1(Label)。
<Label x:Name="lb_freq1" Content="{Binding Value1, Mode=TwoWay}" HorizontalAlignment="Center" Margin="0,10,0,0" />
我不知道如何从那个州继续。我是WPF和C#的新手,如果有人能以任何方式帮助我,我将感激不尽。
主要问题
我已经编辑了我的第一个解决方案,所以如果有人可以看看。我现在设法做的几乎就是我想要的。但有个问题。我想,当我点击OK.Button时,我在Properties.Window上做的“设置”应该改变MainWindow的标签。虽然,当我单击右上角的Cancel.Button或Close.Button时,在Properties.Window上所做的任何更改都不应更改MainWindow上的标签。
此外,当我关闭Properties.Window,然后再次打开它时,CheckBoxes和ComboBox.SelectedItems需要具有与Properties.Window关闭时相同的状态。但这不会发生。
答案 0 :(得分:0)
您应该正确设置两个窗口的DataContext
。目前,您正在多个位置设置和覆盖它。以下是我的建议:
在您的窗口中绑定时使用ElementName
,即wpf1.PWMProperties
和wpf1.MainWindow
,只要您想要绑定到其中的媒体资源。换句话说,给他们一个名字并与他们绑定。例如:
<Window x:Class="wpf1.PWMProperties"
.....
Name="owner">
.....
<StackPanel Margin="0,0,49,0">
.....
ItemsSource="{Binding Path=PeriodComboBoxItems, ElementName=owner}">
</StackPanel>
使用DataContext绑定到ViewModel中的Value1
。将两个Windows的DataContext
设置为ViewModel的实例:
public partial class MainWindow : Window
{
ViewModel viewModel = new ViewModel();
public MainWindow()
{
InitializeComponent();
this.DataContext = viewModel;
}
private void Properties1_Click(object sender, RoutedEventArgs e)
{
var newWindow = new PWMProperties();
newWindow.Owner = this;
newWindow.DataContext = viewModel;
newWindow.Show();
}
}