WPF UserControl DependencyProperty является нулевым в событии щелчка, но не в привязке - PullRequest
0 голосов
/ 23 апреля 2019

У меня есть UserControl под названием ModuleButton. Этот UC имеет некоторые свойства DependencyProperties и некоторые общедоступные свойства ICommand. Я пытаюсь получить кнопку для выполнения двух ICommand, которые у меня есть, когда кнопка нажата, и флажок установлен. Однако нажатие на них ничего не делает.

Сначала я использовал события click как для кнопки, так и для флажка, однако при вызове свойства «Модуль» он получал бы значение «ноль». В духе попыток сделать это как MVVM я переместил их в RelayCommands, думая, что, возможно, это проблема DataContext. Я знаю, что свойства DependencyProperties работают, потому что я связан с ними на стороне XAML, и все выглядит хорошо. Я даже связал свой текст флажка для отображения моего свойства «Модуль» с помощью преобразователя ToString, так как был убежден, что он не был правильно связан, и это так. Я не смог ничего найти с моей конкретной проблемой. У меня есть подозрение, что это связано с моими свойствами ICommand, которые не совпадают с моими свойствами DependencyProperties.

ModuleButton.xaml

Здесь работают все привязки, кроме привязок none DependencyProperties. В настоящее время у меня нет привязанной команды checkbox, так как я пытаюсь сначала устранить неполадки с командой кнопки.

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="50*"/>
        <RowDefinition Height="20*"/>
    </Grid.RowDefinitions>
    <Button Style="{DynamicResource BaseButton}" Command="{Binding ModuleButtonClickCommand}" Content="{Binding Text}" Margin="5"/>
    <DockPanel Grid.Row="1" Margin="0,0,0,4">
        <CheckBox VerticalAlignment="Center" Content="{Binding Module, Converter={StaticResource ToString}}" IsChecked="{Binding IsChecked}" HorizontalAlignment="Left" Foreground="#FFE8E8E8" Margin="0" Style="{DynamicResource myCheckboxStyle}"/>
        <Image Source="/Resources/Info-24.png" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="0,0,5,0" ToolTip="{Binding Description}"/>
    </DockPanel>
</Grid>

ModuleButton.xaml.cs

RelayCommands никогда не выполняются, они работают в других частях моей программы, которые не смешиваются с DependencyProperties.

public partial class ModuleButton : UserControl
{
    public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
        "Text", typeof(string), typeof(ModuleButton),
        new PropertyMetadata("Default Text")
        );

    public static readonly DependencyProperty DescriptionProperty = DependencyProperty.Register(
        "Description", typeof(string), typeof(ModuleButton),
        new PropertyMetadata("Default Description")
        );

    public static readonly DependencyProperty PageProperty = DependencyProperty.Register(
        "Page", typeof(Uri), typeof(ModuleButton),
        new PropertyMetadata(null)
        );

    public static readonly DependencyProperty ModuleProperty = DependencyProperty.Register(
        "Module", typeof(IModule), typeof(ModuleButton),
        new PropertyMetadata(null)
        );

    public static readonly DependencyProperty IsCheckedProperty = DependencyProperty.Register(
        "IsChecked", typeof(bool), typeof(ModuleButton),
        new PropertyMetadata(false)
        );

    public string Text { get => (string)GetValue(TextProperty); set => SetValue(TextProperty, value); }
    public string Description { get => (string)GetValue(DescriptionProperty); set => SetValue(DescriptionProperty, value); }
    public Uri Page { get => (Uri)GetValue(PageProperty); set => SetValue(PageProperty, value); }
    public IModule Module { get => (IModule)GetValue(ModuleProperty); set => SetValue(ModuleProperty, value); }
    public bool IsChecked { get => (bool)GetValue(IsCheckedProperty); set => SetValue(IsCheckedProperty, value); }

    public event EventHandler FavoriteIsCheckedChanged;

    public ModuleButton()
    {
        InitializeComponent();
        FavoriteCheckboxClickedCommand = new RelayCommand(param => FavoriteCheckboxClicked());
        ModuleButtonClickCommand = new RelayCommand(param => ModuleButtonClick());
    }

    public ICommand FavoriteCheckboxClickedCommand { get; private set; }
    public ICommand ModuleButtonClickCommand { get; private set; }

    private void FavoriteCheckboxClicked()
    {
        FavoriteIsCheckedChanged?.Invoke(this, new EventArgs() { });
    }

    private void ModuleButtonClick()
    {
        MessageBox.Show("ModuleButtonClick");
    }
}

Это вкладка, в которой все отображается.

<Page.DataContext>
    <viewmodels:MainToolPageViewModel/>
</Page.DataContext>
<TabControl x:Name="Tabs" Margin="5" ItemsSource="{Binding Tabs}">
    <TabControl.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Header}"/>
        </DataTemplate>
    </TabControl.ItemTemplate>
    <TabControl.ContentTemplate>
        <DataTemplate>
            <ContentPresenter Content="{Binding Content}"/>
        </DataTemplate>
    </TabControl.ContentTemplate>
</TabControl>

Так заполняется список вкладок и его область содержимого.

var cats = ModuleManager.GetCategories();
foreach (var cat in cats.list.OrderBy(x => x.index))
{
    var buttonsHost = new ModulesButtonHostView();
    foreach (var mod in ModuleManager.LoadedModules.Where(x => x.Category == cat.name))
    {
        buttonsHost.Modules.Add(new ModuleItem {
            Text = mod.Name,
            Module = mod,
            Description = mod.Description,
            Page = mod.Page
        });
    }

    Tabs.Add(new MyTabItem() {
        Header = cat.name,
        Content = buttonsHost
    });
}

ModulesButtonHostView.xaml

Модули - это список ModuleItems, которые имеют те же свойства, что и свойства DependencyProperties для элемента управления ModuleButton.

<ItemsControl ItemsSource="{Binding Modules}" ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <controls:ModuleButton/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <WrapPanel FlowDirection="LeftToRight"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>

enter image description here

Что я ожидаю, так это то, что когда я нажимаю кнопку «Модуль», он может использовать свойство «Модуль» для загрузки этого модуля, над которым у меня работает эта часть кода, это фактическое использование свойства «Модуль» в RelayCommand, что я не могу понять, почему он нулевой.

Edit:

Добавление изображения вопроса с обязательным предложением

enter image description here

1 Ответ

0 голосов
/ 24 апреля 2019

Вы должны установить источник или DataContext привязок для самого UserControl:

<Grid DataContext="{Binding RelativeSource={RelativeSource AncestorType=UserControl}}">
    <Grid.RowDefinitions>
        <RowDefinition Height="50*"/>
        <RowDefinition Height="20*"/>
    </Grid.RowDefinitions>
    <Button Style="{DynamicResource BaseButton}" Command="{Binding ModuleButtonClickCommand}" Content="{Binding Text}" Margin="5"/>
    <DockPanel Grid.Row="1" Margin="0,0,0,4">
        <CheckBox VerticalAlignment="Center" Content="{Binding Module, Converter={StaticResource ToString}}" IsChecked="{Binding IsChecked}" HorizontalAlignment="Left" Foreground="#FFE8E8E8" Margin="0" Style="{DynamicResource myCheckboxStyle}"/>
        <Image Source="/Resources/Info-24.png" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="0,0,5,0" ToolTip="{Binding Description}"/>
    </DockPanel>
</Grid>

Если вы этого не сделаете, среда выполнения будет искать эти свойства в классе ModuleItem.

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