Aquarius-Michael
@Aquarius-Michael
Программист и железячник

Как отслеживать изменяемые данные?

Есть такой класс, который имеет заголовок вкладки и содержимое панели (TabControl).
public class TabInfo
    {
        public string Header { get; set; }
        public Panel Content { get; set; }
    }

Данный класс привязан ко вкладкам через ObservableCollection.
Вот в содержимом панели (Panel) существуют две строковые записи, которые ежесекундно обновляются. Вкладок у меня может много. Но мне нужно сделать так, чтобы записи в StatusBar отображалась информация двух строковых записей из активного контента.

<Window x:Class="ExperiencePanelsWPF.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-namespace:ExperiencePanelsWPF"
        mc:Ignorable="d"
        Title="MainWindow" Height="1024" Width="1280" Background="White" WindowStartupLocation="CenterScreen" WindowState="Maximized">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Grid.Resources>
            <Style TargetType="{x:Type MenuItem}">
                <Setter Property="Padding" Value="12,8"/>
            </Style>
        </Grid.Resources>
        <Menu Grid.Row="0" Background="White">
            <MenuItem Header="Устройства">
                <MenuItem Header="Добавить устройство" Click="AddTab"/>
                <MenuItem Header="Закрыть устройство (не работает)"/>
            </MenuItem>
            <MenuItem Header="Дополнительные опции для устройства">
                <MenuItem Header="Загрузка файла на десериалайзер" Click="LoadFileForGTX"/>
                <MenuItem Header="Работа с Flash-накопителем"/>
                <MenuItem Header="Общий сброс" Name="GlobalReset"/>
            </MenuItem>
            <MenuItem Header="Проверка элементов (тестирование)">
                <MenuItem Header="Добавить элемент с особым значением (тестирование)" Click="SpecialAdd"/>
                <MenuItem Header="Проверка элемента (тестирование)" Click="CheckElement"/>
                <MenuItem Header="Присвоить значение элемента (тестирование)" Click="CheckSet"/>
            </MenuItem>
        </Menu>
        <Grid Grid.Row="1">
            <TabControl Grid.Row="1" ItemsSource="{Binding ListGTP}" SlectedItem="{Binding SelectedTab}" Name="TabGTP" Background="#FFF9F9F9" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" SelectionChanged="DeviceChanged">
                <TabControl.ContentTemplate>
                    <DataTemplate>
                        <ContentControl Content="{Binding Path=Content, Mode=TwoWay}"/>
                    </DataTemplate>
                </TabControl.ContentTemplate>
                <TabControl.ItemTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Path=Header}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
                    </DataTemplate>
                </TabControl.ItemTemplate>
            </TabControl>
        </Grid>
        <StatusBar Grid.Row="2" Background="#FF007ACC" Foreground="White">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="80"/>
                    <ColumnDefinition Width="180"/>
                    <ColumnDefinition Width="80"/>
                    <ColumnDefinition Width="128"/>
                    <ColumnDefinition Width="210"/>
                    <ColumnDefinition Width="32"/>
                    <ColumnDefinition Width="64"/>
                    <ColumnDefinition Width="210"/>
                    <ColumnDefinition Width="256"/>
                    <ColumnDefinition Width="210"/>
                    <ColumnDefinition Width="128"/>
                    <ColumnDefinition/>
                    <ColumnDefinition/>
                    <ColumnDefinition/>
                </Grid.ColumnDefinitions>
                <StatusBarItem Grid.Column="0" Content="Устройство: " HorizontalContentAlignment="Right"/>
                <StatusBarItem Grid.Column="1" Content="" Name="SelectedDevice"/>
                <StatusBarItem Grid.Column="2" Content="Состояние: " HorizontalContentAlignment="Right"/>
                <StatusBarItem Grid.Column="3" Content="" Name="StatusDevice"/>
                <StatusBarItem Grid.Column="4" Content="Количество запущенных устройств: " HorizontalContentAlignment="Right"/>
                <StatusBarItem Grid.Column="5" Content="" Name="CountDevice"/>
                <StatusBarItem Grid.Column="6" Content="###"/>
                <StatusBarItem Grid.Column="7" Content="Скорость приёма данных от ПЛИС: " HorizontalContentAlignment="Right"/>
                <StatusBarItem Grid.Column="8" Name="SpeedLoadingPC" DataContext="{Binding SelectedTab}" Content="{Binding Content.TestSpeedLoadingPC}"/>
                <StatusBarItem Grid.Column="9" Content="Скорость передачи данных к ПЛИС: " HorizontalContentAlignment="Right"/>
                <StatusBarItem Grid.Column="10" Name="SpeedLoadingFPGA" Content="###"/>
            </Grid>
        </StatusBar>
    </Grid>
</Window>
  • Вопрос задан
  • 259 просмотров
Решения вопроса 2
Добавте переменую в view model(которая содержит колекцию) и забиндите на нее SelectedItem. Ну а дальше биндим status bar на нее.

Также что-то подобное можно провернуть в xaml при помощи ElementName, который будет ссылаться "табко контайнер" и вытаскивать из него SelectedItem.

UPD
Не совсем, тут два варианта первый через view model:
1. Во view model добавляем поле SelectedTab.
2. Биндим к нему выбраню табку
<TabControl SelectedItem="{Binding SelectedTab}"/>
3. Биндим статус бар
...
<StatusBarItem>
   <TextBlock DataContext="{Binding SelectedTab}" Text="{Binding FirstField}" />
</StatusBarItem>
<Separator Grid.Column="1" />
<StatusBarItem Grid.Column="2">
   <TextBlock DataContext="{Binding SelectedTab}" Text="{Binding SecondField}" />
 </StatusBarItem>
...

Второй способ ElementName
1. Даем имя "табоконтейнеру"
<TabControl x:Name="tabControl" />
2. Биндимся на него
...
<StatusBarItem>
    <TextBlock DataContext="{Binding ElementName=tabControl, Path=SelectedItem}" Text="{Binding FirstField}" />
</StatusBarItem>
<Separator Grid.Column="1" />
<StatusBarItem Grid.Column="2">
   <TextBlock DataContext="{Binding ElementName=tabControl, Path=SelectedItem}" Text="{Binding SecondField}" />
</StatusBarItem>
...


И да, вам тут понадобится INotifyPropertyChanged. Первый вариант предпочтительней поскольку логическая связь устанавливается на уровне view model, а не в presentation.
Ответ написан
andrewpianykh
@andrewpianykh
Реализуйте интерфейс INotifyPropertyChanged для модели (Panel).

public class Panel : INotifyPropertyChanged
{
	private string field1;
	private string field2;

	public event PropertyChangedEventHandler PropertyChanged;
	
	public string Field1
	{
		get{return field1;}
		set{field1 = value; NotifyPropertyChanged("Field1");}
	}
	
	public string Field2
	{
		get{return field2;}
		set{field2 = value; NotifyPropertyChanged("Field2");}
	}
	
	private void NotifyPropertyChanged(string propertyName = "")
	{
		if (PropertyChanged != null)
		{
			PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
		}
	}
}
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
Aquarius-Michael
@Aquarius-Michael Автор вопроса
Программист и железячник
Спасибо всем, что помогли, как решить вопрос. Оказывается, что для этого надо ещё при инициализации объекта сделать подписку на событие, чтобы забрать данные при возникновении событии.. Тогда будет работать.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы