WPF UserControl DependencyProperty在click事件中为null,但在绑定中不为null

时间:2019-04-23 18:27:27

标签: c# wpf data-binding

我有一个称为ModuleButton的UserControl。该UC具有一些DependencyProperties和一些公共ICommand属性。我试图让该按钮执行两个ICommand,当单击该按钮并选中该复选框时,它们就会执行该操作。但是,单击它们不会执行任何操作。

我首先在按钮和复选框上都使用了click事件,但是,当调用属性“ Module”时,它将说为null。本着尝试在MVVM中执行此操作的精神,我将其移至RelayCommands,以为可能是DataContext问题。我知道DependencyProperties可以正常工作,因为我在XAML方面已绑定到它们,并且一切看起来都很好。我什至绑定了复选框文本以使用ToString转换器显示我的“ Module”属性,因为我确信这并没有正确绑定。我没有找到与我的特定问题有关的任何内容。我怀疑这与我的ICommand属性有关,与我的DependencyProperties不在同一个上下文中。

ModuleButton.xaml

除了无DependencyProperties绑定之外,所有绑定在这里都有效。我目前没有绑定复选框命令,因为我想先对按钮命令进行故障排除。

<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

RelayCommand从不执行,它们可以在我程序的其他部分中工作,而这些部分没有与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

模块是具有与ModuleButton控件上的DependencyProperties相同属性的ModuleItem列表。

<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

我希望发生的事情是,当我单击“模块按钮”时,它能够使用Module属性来加载该模块,而我的那部分代码正在工作,这实际上是使用RelayCommand,我不知道为什么它为空。

编辑:

添加具有约束力建议的问题图片

enter image description here

1 个答案:

答案 0 :(得分:0)

您应将绑定的源或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类中查找这些属性。