我的C#WPF应用程序遇到了一个非常棘手且令人讨厌的问题。我想对于一个好的程序员来说解决它并不是什么大问题,但是我还不知道如何解决它。对于学校,我必须编写一个描述过程的应用程序。因此,我通过XML文件获取数据,必须计算一些值,将其显示给用户交互等。最后,输出又是一个文件,可以进一步处理。
为此,我得到了不同的UserControl,它们描述了不同的模块,例如,一个用于数据导入,另一个用于计算和显示值,等等。主窗口就像是自由空间或占位符,根据我们在过程中的位置,可以在其中加载不同的模块。
我现在的问题是,我在UserControl中计算出的值不会分别显示在我的UI和应用程序中,我也不知道为什么。 0是唯一传送到应用程序的值。对此感到好奇的是,在Debugger中,这些值是正确的,但是在显示本身中,只有0。
好吧,所以我现在向您展示不同文件的代码(我不是最好的程序员,因此有时代码可能有点脏)。
我有一个主用户控件,我们将其称为UC_Main,在此UserControl中,您可以根据选中UC_Main中的哪个单选按钮在3个其他用户控件之间进行切换。 (始终显示UC_Main,因为在该窗口中只有3个单选按钮,并且下面有一个很大的可用空间,在其中装载了不同的UserControl 1、2和3)。
UC_Main.xaml
<UserControl.Resources>
<DataTemplate x:Name="UC1_Template" DataType="{x:Type local:UC1}">
<local:UC1 DataContext="{Binding}" />
</DataTemplate>
<DataTemplate x:Name="UC2_Template" DataType="{x:Type local:UC2}">
<local:UC2 DataContext="{Binding}" />
</DataTemplate>
<DataTemplate x:Name="UC3_Template" DataType="{x:Type local:UC3}">
<local:UC3 DataContext="{Binding}" />
</DataTemplate>
</UserControl.Resources>
<Border Padding="10">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<!-- In the First Row there are the radio buttons in the second the
different UserControls 1, 2 or 3 -->
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<materialDesign:ColorZone Mode="PrimaryMid" Width="400" HorizontalAlignment="Left">
<StackPanel Grid.Row="0" Orientation="Horizontal" Margin="2">
<RadioButton x:Name="UC1_radiobutton" Checked="UC1_radiobutton_Checked"
Style="{StaticResource MaterialDesignTabRadioButton}"
Margin="4"
IsChecked="True"
Content="UserControl1" />
<RadioButton x:Name="UC2_radiobutton" Checked="UC2_radiobutton_Checked"
Style="{StaticResource MaterialDesignTabRadioButton}"
Margin="4"
IsChecked="False"
Content="UserControl2" />
<RadioButton x:Name="UC3_radiobutton" Checked="UC3_radiobutton_Checked"
Style="{StaticResource MaterialDesignTabRadioButton}"
Margin="4"
IsChecked="False"
Content="UserControl3" />
</StackPanel>
</materialDesign:ColorZone>
<ContentControl Grid.Row="1" Content="{Binding}" />
</Grid>
</Border>
</UserControl>
UC_Main.xaml.cs
public partial class UC_Main : UserControl
{
public UC_Main()
{
InitializeComponent();
}
private void UC1_radiobutton_Checked(object sender, RoutedEventArgs e)
{
DataContext = new UC1();
}
private void UC2_radiobutton_Checked(object sender, RoutedEventArgs e)
{
DataContext = new UC2();
}
private void UC3_radiobutton_Checked(object sender, RoutedEventArgs e)
{
DataContext = new UC3();
}
}
}
为简单起见,我只向您显示UserControl 1的代码,因为UC 2和3在其他变量或值旁边非常相似。
UC1.xaml
<Border Padding="10">
<StackPanel>
<!-- To keep the example simple, I got 1 Row and 2 Colums; in each
is one TextBox -->
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="2*" />
</Grid.ColumnDefinitions>
<TextBox x:Name="TextBox1" Grid.Column="0" IsTabStop="False"
Text="{Binding Path=variable1, Mode=TwoWay}"
VerticalAlignment="Center"
HorizontalAlignment="Center"
TextAlignment="Center"
Height="25"
Width="85"
Foreground="DarkGray"
IsReadOnly="True" />
<TextBox x:Name="TextBox2" Grid.Column="1" IsTabStop="False"
Text="{Binding Path=variable2, Mode=TwoWay}"
VerticalAlignment="Center"
HorizontalAlignment="Center"
TextAlignment="Center"
Height="25"
Width="85"
Foreground="DarkGray"
IsReadOnly="True" />
</Grid>
</StackPanel>
</Border>
</UserControl>
UC_1.xaml.cs
public partial class UC1 : UserControl
{
public MainWindow Speaker;
public ValueStore vs;
public UC1()
{
InitializeComponent();
Speaker = MainWindow.AppWindow;
vs = new ValueStore();
DataContext = vs;
}
public void calc_data()
{
// I get the data from the data import (XML-File), which is saved in
// a dictionary (strings), converting them to int (so I can do some
// math operations) and save them in my variable.
// UC_Other is a UserControl, where the data import happens
// dict_other is the dictionary, where the data from the import is
// saved
vs.variable1 =
Convert.ToInt32(MainWindow.AppWindow.UC_other.dict_other["0"].Amount);
vs.variable2 =
Convert.ToInt32(MainWindow.AppWindow.UC_other.dict_other["1"].Amount);
}
我之前在UserControl中调用了函数calc_data(),因此在UserControl出现之前,已计算数据并将其保存在变量中。我声明了UC1的新公共实例,并通过UC1.calc_data();调用了该函数。 (链接到一个正在加载我的UC_Main的按钮)。
ValueStore.cs
public class ValueStore : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
if(PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
private int _variable1;
public int variable1
{
get { return _variable1; }
set { _variable1 = value; OnPropertyChanged("variable1"); }
}
private int _variable2;
public int variable2
{
get { return _variable2; }
set { _variable2 = value; OnPropertyChanged("variable2"); }
}
在调用calc_data()方法后在调试器中查看时,值正确保存在ValueStore实例中,并且文本框在调试器中向我显示了正确的值(调试器说“名称: TextBox1”和“值:{System.Windows.Controls.TextBox:100}”; 100是我从字典中获得的值),但是在我的应用程序本身中,仅显示了值0。
我真正不了解的是,当我在ValueStore.cs中将类型从变量1更改为字符串并将其保存在方法calc_data()(没有Convert.ToInt32)的变量中时,它甚至没有在我的应用程序中再显示0,但是在调试器中,值仍然为“ 100”。
答案 0 :(得分:0)
这里有几件事,但是我最大的猜测是为什么调试值正确而又没有更新到GUI的原因在这里:
public partial class UC_Main : UserControl
{
public UC_Main()
{
InitializeComponent();
}
private void UC1_radiobutton_Checked(object sender, RoutedEventArgs e)
{
DataContext = new UC1();
}
private void UC2_radiobutton_Checked(object sender, RoutedEventArgs e)
{
DataContext = new UC2();
}
private void UC3_radiobutton_Checked(object sender, RoutedEventArgs e)
{
DataContext = new UC3();
}
}
您将在用户控件后面创建这些类代码的新实例。但是UC_Main.xaml
已经创建了usercontrol对象,因此在运行时,您有两个对象,例如UC1类,一个是绑定到GUI的对象,另一个是存储和更新值的对象。您在GUI上看到的那个没有任何值更新,这就是为什么您什么都没看到的原因。
我目前无法自己测试代码,但是从我可以看到的是问题所在。 此外,这对我来说有点令人困惑,为什么要使用数据绑定进行代码隐藏。 (您正在使用UC类的代码作为主类的数据上下文,这是..weird;)我认为在您的情况下,实际上并不需要任何数据绑定,但是,如果您想对数据绑定进行处理您可能应该阅读MVVM)