Связывание WPF MainWindow от UserControl, PropertyChanged не сработало - PullRequest
0 голосов
/ 17 апреля 2019

Я новичок в WPF и сталкиваюсь с проблемой связывания. У меня есть MainWindow с Rectangle, который использует привязку для изменения визуальных атрибутов. Код XAML выглядит следующим образом:

<Rectangle Height="72" Canvas.Left="1011" RadiusY="6" RadiusX="6" StrokeThickness="2" Width="82" Canvas.Top="8">
    <Rectangle.Style>
        <Style TargetType="Rectangle">
            <Style.Triggers>
                <DataTrigger Binding="{Binding BddState}" Value="True">
                    <Setter Property="Fill">
                      <Setter.Value>
                        <ImageBrush ImageSource="Pictures/BDD_on.png" Stretch="Uniform" />
                      </Setter.Value>
                    </Setter>

                </DataTrigger>
                <DataTrigger Binding="{Binding BddState}" Value="False">
                    <Setter Property="Fill">
                        <Setter.Value>
                            <ImageBrush ImageSource="Pictures/Bdd_off.png" Stretch="Uniform" />
                        </Setter.Value>
                    </Setter>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Rectangle.Style>
</Rectangle>

Я создал класс модели представления для управления привязкой:

public class ViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(String propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
            handler(this, new PropertyChangedEventArgs(propertyName));
    }


    private Boolean _bddstate;
    public Boolean BddState
    {
        get { return _bddstate; }
        set
        {
            _bddstate = value;
            OnPropertyChanged("BddState");
        }
    }
}

Привязка хорошо работает из MainWindow, используя:

private ViewModel _viewModel = new ViewModel();

public MainWindow()
{
    InitializeComponent();
    this.DataContext = _viewModel;
    _viewModel.BddState = true;        
}

Внутри MainWindow я использую StackPanel для загрузки различных UserControl (MainWindow действует как заголовок). Мое беспокойство связано с UserControl; значение BddState изменяется соответственно, но ничего не отражается на MainWindow пользовательском интерфейсе. В то же время я вижу, что обработчик модели представления всегда null.

Что я делаю не так?

Заранее спасибо за вашу поддержку.

Обновление: вот код пользовательского элемента управления:

<Grid Background="#FFECECEC" Height="706" VerticalAlignment="Top">
    <Label x:Name="label" Content="HOME" HorizontalAlignment="Left" Margin="525,8,0,0" VerticalAlignment="Top" FontWeight="Bold" Foreground="{DynamicResource gray_2}" FontSize="20"/>
    <Label x:Name="label_Copy" Content="General Info" HorizontalAlignment="Left" Margin="441,34,0,0" VerticalAlignment="Top" Foreground="{DynamicResource gray_2}" FontSize="18"/>
    <Button x:Name="button" Content="Button" HorizontalAlignment="Left" Margin="441,214,0,0" VerticalAlignment="Top" Width="107" Height="36" Click="button_Click"/>


</Grid>

для кода, это просто следующее:

 public partial class Home : UserControl
{
    public Home()
    {
        InitializeComponent();
    }

    private void button_Click(object sender, RoutedEventArgs e)
    {
        ViewModel _vm = new ViewModel();
        _vm.BddState = true;
    }
}

Когда я нажимаю кнопку Home UC, обработчик ViewModel становится пустым, и привязка к прямоугольнику MainWindow не действует

вот какое-то обновление по примеру Энди (это может помочь) приведение основного текста данных к текстовому принципу работает:

 MainWindowViewModel viewModel = App.Current.MainWindow.DataContext as MainWindowViewModel;
        if (viewModel != null)
        {
            viewModel.BddState = true;
        }

1 Ответ

1 голос
/ 17 апреля 2019

Я изменил вашу разметку на:

    <Canvas Name="MyCanvas" >
        <Rectangle Height="72"  RadiusY="6" RadiusX="6" StrokeThickness="2" Width="82" Canvas.Top="8">
            <Rectangle.Style>
                <Style TargetType="Rectangle">
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding BddState}" Value="True">
                            <Setter Property="Fill" Value="Green"/>
                        </DataTrigger>
                        <DataTrigger Binding="{Binding BddState}" Value="False">
                            <Setter Property="Fill" Value="Yellow"/>
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </Rectangle.Style>
        </Rectangle>
    </Canvas>

Который не зависит ни от какого изображения и не Canvas.Left.

Я получаю зеленый прямоугольник.

Возможные причины, по которым вы ничего не видите, включают:

Ваше окно уже, чем 1011px, и Canvas.Left = "1011" означает, что ваш прямоугольник находится за пределами вашего окна.

Ваши пути к изображениям не работают.

Равномерное растяжение создает проблему, и часть прямоугольника, на которой есть какое-либо изображение, находится за пределами экрана.

Затем я изменил это далее, чтобы изначально установить bddstate true через частное поле поддержки в viewmodel. Добавлена ​​тумблер с привязкой ischecked к bddstate. Это успешно переключается между желтым и зеленым.

Вот рабочая версия, включающая пользовательский контроль. Я унаследовал MainWindowViewModel от BaseViewModel, который был в моем тестовом образце.

MainWindow:

 <Window.DataContext>
    <local:MainWindowViewModel/>
</Window.DataContext>
<Grid>
    <Canvas Name="MyCanvas" >
        <Rectangle Height="72"  RadiusY="6" RadiusX="6" StrokeThickness="2" Width="82" Canvas.Top="8">
            <Rectangle.Style>
                <Style TargetType="Rectangle">
                    <Setter Property="Fill" Value="Green"/>
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding BddState}" Value="False">
                            <Setter Property="Fill" Value="Yellow"/>
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </Rectangle.Style>
        </Rectangle>
    </Canvas>
    <local:UserControl1 Height="30" Width="100"/>
</Grid>

Модель представления:

public class MainWindowViewModel : BaseViewModel
{
    private Boolean _bddstate = true;
    public Boolean BddState
    {
        get { return _bddstate; }
        set
        {
            _bddstate = value;
            RaisePropertyChanged("BddState");
        }
    }

UserControl1

    <ToggleButton Width="100" Height="30" Content="Toggle" IsChecked="{Binding BddState, Mode=TwoWay}"/>

BaseViewModel

public  class BaseViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected void RaisePropertyChanged([CallerMemberName] String propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

Там нет кода.

И это все еще работает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...