C#WPF-变量值将不会显示在文本框中(DataContext?)

时间:2018-12-20 16:08:12

标签: c# wpf data-binding datacontext

我的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”。

1 个答案:

答案 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)