C# WPF - 变量值不会显示在文本框上(DataContext?)
C# WPF - variable value won't display on Textboxes (DataContext?)
我的 C# WPF 应用程序遇到了一个非常棘手和烦人的问题。我想一个好的程序员解决它并不是什么大问题,但我还不知道如何解决它。对于学校,我必须编写一个描述过程的应用程序。所以我通过 XML-File 获取数据,必须计算一些值,为用户交互等显示它们,最后输出又是一个文件,可以进一步处理。
为此,我得到了不同的用户控件,它描述了不同的模块,例如,一个用于数据导入,另一个用于计算和显示值等等。 Main Window 就像免费的 space 或占位符,根据我们在进程中的位置加载不同的模块。
我现在的问题是,我在我的 UserControl 中计算的值不会分别显示在我的 UI 我的应用程序中,我真的不知道为什么。 0 是传输到应用程序的唯一值。奇怪的是,在调试器中的值是正确的,但在显示本身中只有一个 0。
好的,现在我向您展示不同文件的代码(我不是最好的程序员,所以代码有时可能有点脏)。
我有一个主用户控件,我们称它为 UC_Main,在此用户控件中,您可以根据选中 UC_Main 中的哪个单选按钮在 3 个不同的其他用户控件之间切换。 (UC_Main 始终显示,因为这里只有 3 个单选按钮,下面是一个很大的空闲 space,其中加载了不同的 UserControls 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 的一个新 public 实例,并通过 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 实例中,并且文本框在调试器中向我显示正确的值在那里(调试器说 "Name: TextBox1" 和 "Value: {System.Windows.Controls.TextBox: 100}";100 是我从字典中得到的值),但在我的应用程序本身中只显示值 0。
我不太明白的是,当我在 ValueStore.cs 中将类型从 variable1 更改为 string 并将其保存在方法 calc_data()(without Convert. ToInt32),它在我的应用程序中甚至不再显示 0,但在调试器中仍然有值“100”。
这里有几件事,但我最好的猜测是为什么在 none 更新到 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();
}
}
您正在为用户控件创建这些 class 代码隐藏的新实例。但是用户控件对象已经由 UC_Main.xaml
创建,因此在运行时,您有两个对象,例如 UC1 class,一个绑定到您的 GUI,另一个用于存储和更新您的值.您在 GUI 上看到的那个没有得到任何值更新,这就是为什么您看不到任何东西的原因。
我目前无法自己测试代码,但据我所知,这就是问题所在。
此外,我有点困惑,为什么要使用数据绑定进行代码隐藏。
(您正在使用 UC-classes 的代码隐藏作为主要 class 的数据上下文,这是....奇怪的;)我认为在您的情况下,实际上不需要任何数据绑定,但是,如果你想用数据绑定做一些事情,你可能应该阅读 MVVM)
我的 C# WPF 应用程序遇到了一个非常棘手和烦人的问题。我想一个好的程序员解决它并不是什么大问题,但我还不知道如何解决它。对于学校,我必须编写一个描述过程的应用程序。所以我通过 XML-File 获取数据,必须计算一些值,为用户交互等显示它们,最后输出又是一个文件,可以进一步处理。
为此,我得到了不同的用户控件,它描述了不同的模块,例如,一个用于数据导入,另一个用于计算和显示值等等。 Main Window 就像免费的 space 或占位符,根据我们在进程中的位置加载不同的模块。
我现在的问题是,我在我的 UserControl 中计算的值不会分别显示在我的 UI 我的应用程序中,我真的不知道为什么。 0 是传输到应用程序的唯一值。奇怪的是,在调试器中的值是正确的,但在显示本身中只有一个 0。
好的,现在我向您展示不同文件的代码(我不是最好的程序员,所以代码有时可能有点脏)。
我有一个主用户控件,我们称它为 UC_Main,在此用户控件中,您可以根据选中 UC_Main 中的哪个单选按钮在 3 个不同的其他用户控件之间切换。 (UC_Main 始终显示,因为这里只有 3 个单选按钮,下面是一个很大的空闲 space,其中加载了不同的 UserControls 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 的一个新 public 实例,并通过 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 实例中,并且文本框在调试器中向我显示正确的值在那里(调试器说 "Name: TextBox1" 和 "Value: {System.Windows.Controls.TextBox: 100}";100 是我从字典中得到的值),但在我的应用程序本身中只显示值 0。
我不太明白的是,当我在 ValueStore.cs 中将类型从 variable1 更改为 string 并将其保存在方法 calc_data()(without Convert. ToInt32),它在我的应用程序中甚至不再显示 0,但在调试器中仍然有值“100”。
这里有几件事,但我最好的猜测是为什么在 none 更新到 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();
}
}
您正在为用户控件创建这些 class 代码隐藏的新实例。但是用户控件对象已经由 UC_Main.xaml
创建,因此在运行时,您有两个对象,例如 UC1 class,一个绑定到您的 GUI,另一个用于存储和更新您的值.您在 GUI 上看到的那个没有得到任何值更新,这就是为什么您看不到任何东西的原因。
我目前无法自己测试代码,但据我所知,这就是问题所在。 此外,我有点困惑,为什么要使用数据绑定进行代码隐藏。 (您正在使用 UC-classes 的代码隐藏作为主要 class 的数据上下文,这是....奇怪的;)我认为在您的情况下,实际上不需要任何数据绑定,但是,如果你想用数据绑定做一些事情,你可能应该阅读 MVVM)