C # WPF - значение переменной не будет отображаться в текстовых полях (DataContext?) - PullRequest
0 голосов
/ 20 декабря 2018

У меня действительно сложная и раздражающая проблема с моим C # WPF-приложением.Я думаю, что для хорошего программиста это не проблема, но я пока не знаю, как это исправить.Для школы я должен запрограммировать приложение, которое отображает процесс.Таким образом, я получаю данные в виде XML-файла, мне нужно вычислить некоторые значения, отобразить их для взаимодействия с пользователем и т. Д., И в конце получается снова файл, который можно обрабатывать дальше.

Для этого яполучил разные UserControls, которые изображают разные модули, например, один для импорта данных, другой для вычисления и отображения значений и так далее.Главное окно похоже на свободное место или заполнитель, в который загружаются различные модули, в зависимости от того, где мы находимся в процессе.

Моя проблема сейчас заключается в том, что значения, которые я вычисляю в моем UserControl, не будутотобразить в моем пользовательском интерфейсе, соответственно, мое приложение, и я не знаю, почему.0 - единственное значение, которое передается в приложение.Любопытно, что в отладчике значения верны, но на самом дисплее есть только 0.

Хорошо, поэтому я покажу вам код различных файлов (я нелучший программист, так что, может быть, код иногда немного грязный)проверено.(UC_Main отображается всегда, потому что в нем только 3 переключателя, а внизу - большое свободное пространство, в которое загружаются различные пользовательские элементы управления 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);
    }

Я вызываю функцию calc_data () в UserControl раньше, поэтому данные вычисляются и сохраняются в моих переменных до того, как появится мой 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.

Что я на самом деле не понимаю, так это когда я меняю тип сПеременная1 в строку в моем ValueStore.cs и сохранить ее в моей переменной в методе calc_data () (без Convert.ToInt32), в моем приложении он даже больше не показывает 0, но в отладчике все еще есть значение"100".

1 Ответ

0 голосов
/ 20 декабря 2018

Здесь есть несколько вещей, но я лучше всего угадаю, почему ваши значения отладки верны, в то время как ни один не обновляется в 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();            
    }  
}

Вы создаете новые экземпляры этих классовкод позади пользовательского контроля.Но объекты usercontrol уже созданы UC_Main.xaml, поэтому во время выполнения у вас есть два объекта, например, класс UC1, один из которых связан с вашим графическим интерфейсом, а другой - где вы храните и обновляете свои значения.Тот, который вы видите в своем графическом интерфейсе, не получает обновлений значений, поэтому вы ничего не видите.

В настоящее время я сам не могу протестировать код, но из того, что я вижу, в этом и заключается проблема.Кроме того, меня немного смущает, почему вы используете привязку данных для кода.(Вы используете выделенный код UC-классов в качестве datacontext для основного класса, что .... странно;) Я думаю, что в вашем случае никакой привязки данных вообще не требуется, однако, если вы хотите делать вещи с привязкой данныхвы, вероятно, должны прочитать о MVVM)

...