首页 > 解决方案 > 通知已在 WPF 中的 UserControl 中选择了 RadioButton

问题描述

我试图让视图模型中的按钮识别另一个视图模型中的单选按钮(在第一个视图模型上激活的用户控件)已被选中,从而启用第一个视图模型中的按钮。AlbumsDisplayViewModel我的基本视图模型中有一个 UserControl BaseViewModel。在BaseViewXAML 中有一个按钮 (OpenAlbum),它应该在AlbumsDisplayView选中单选按钮时启用(请参阅 CanOpenAlbum)。

基本视图 XAML:

<Canvas x:Name="cnvsInputWrapper" Background="LightGray"
                Grid.Column="4" Grid.Row="1" Grid.RowSpan="4"
                Margin="5">
            <Canvas.OpacityMask>
                <VisualBrush Visual="{Binding ElementName=maskRoundEdges}" />
            </Canvas.OpacityMask>

            <DockPanel Margin="15, 25">
                <ContentControl x:Name="ActiveItem" />
            </DockPanel>
        </Canvas>

        <!-- Action Buttons section -->
        <Grid Grid.Row="3" Grid.Column="1" Grid.RowSpan="2">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="12" />
                <ColumnDefinition Width="auto" />
                <ColumnDefinition Width="auto" />
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="12" />
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="12" />
                <RowDefinition Height="auto" />
                <RowDefinition Height="auto" />
                <RowDefinition Height="*" />
                <RowDefinition Height="12" />
            </Grid.RowDefinitions>

            <Button Grid.Row="1" Grid.Column="1" x:Name="OpenAlbum" 
                    IsEnabled="{Binding CanOpenAlbum}">
                <StackPanel Orientation="Vertical">
                    <TextBlock>Open</TextBlock>
                    <TextBlock>Album</TextBlock>
                </StackPanel>
            </Button>

        </Grid>

BaseViewModel C#:

public class BaseViewModel : Conductor<object>
    {
        private AlbumsDisplayViewModel m_vmAlbumsDisplay;    // Initialized in another function.

        public BaseViewModel()
        {
        }

        public bool CanOpenAlbum() => (m_vmAlbumsDisplay != null) && (m_vmAlbumsDisplay.GetSelectedAlbum() != null);

        public void OpenAlbum()
        {
            AlbumModel album = m_vmAlbumsDisplay.GetSelectedAlbum();
            //ActivateItem(/*albumViewModel(album)*/);
        }
}

相册显示视图 XAML:

<ItemsControl x:Name="Albums" FlowDirection="LeftToRight"
                          Margin="10, 0">
                <ItemsControl.ItemTemplate>
                    <DataTemplate DataType="{x:Type vms:AlbumViewModel}">
                        <StackPanel Orientation="Horizontal" Margin="0, 5">

                            <RadioButton GroupName="rdbtnAlbums"
                                         IsChecked="{Binding IsSelected}" />

                            <!-- Album Details -->
                        </StackPanel>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>

相册DisplayViewModel C#:

    class AlbumsDisplayViewModel : Screen
    {
        private ObservableCollection<AlbumViewModel> m_albums;

        public AlbumsDisplayViewModel()
        {
        }

        public ObservableCollection<AlbumViewModel> Albums
        {
            get { return m_albums; }
            set
            {
                m_albums = value;
                NotifyOfPropertyChange(() => Albums);
            }
        }

        public AlbumModel GetSelectedAlbum()
        {
            AlbumModel res = null;

            foreach (var vmAlbum in Albums)
            {
                if (vmAlbum.IsSelected)
                {
                    res = vmAlbum.Album;
                    break;
                }
            }

            return res;
        }
    }

最后,AlbumViewModel C#:


    class AlbumViewModel : Screen
    {
        private AlbumModel m_albumModel;
        private bool m_isSelected;

        public AlbumViewModel(AlbumModel albumModel)
        {
            m_albumModel = albumModel;
        }

        public AlbumModel Album
        {
            get { return m_albumModel; }
            set
            { 
                m_albumModel = value;
                NotifyOfPropertyChange(() => Album);
            }
        }
        public bool IsSelected
        {
            get { return m_isSelected; }
            set
            {
                m_isSelected = value;
                NotifyOfPropertyChange(() => IsSelected);
            }
        }
   }

我预计当 AlbumViewModel 中的 IsSelected 发生更改时(当用户选择单选按钮时),将启用 OpenAlbum 按钮,因为 CanOpenAlbum 将返回 true,但我意识到由于某种原因甚至没有调用 CanOpenAlbum。我需要做什么才能在选择单选按钮时通知 CanOpenAlbum 被调用?

标签: c#wpfcaliburn.micro

解决方案


找了很久的答案,我决定还是找一个更好的解决方案,而不是一个答案。我发现 ListBox 元素有一个 SelectedItem 属性,它消除了对单选按钮的需要。最终,我用 ListBox 替换了 ItemsControl,我对结果很满意。

AlbumDisplayView XAML(仅此已更改):

<ScrollViewer x:Name="Scroller" Height="300"
                      FlowDirection="RightToLeft">
            <ListBox x:Name="Albums" FlowDirection="LeftToRight"
                     Background="Transparent" Margin="10, 0"
                     BorderThickness="0" SelectedItem="{Binding SelectedAlbum}">
                <ItemsControl.ItemTemplate>
                    <DataTemplate DataType="{x:Type vms:AlbumViewModel}">
                        <StackPanel Orientation="Horizontal" Margin="0, 5">

                            <!-- Album Details -->
                            <StackPanel Orientation="Vertical">
                                <StackPanel Grid.Row="1" Grid.Column="1"
                                        Orientation="Horizontal" Margin="12, 0">
                                    <TextBlock Text="{Binding Album.Name}" />
                                    <TextBlock Text=" - User@" />
                                    <TextBlock Text="{Binding Album.OwnerID}" />
                                </StackPanel>
                                <TextBlock Text="{Binding Album.CreationDate}"
                                           FontSize="12" Margin="12, 0" />
                            </StackPanel>
                        </StackPanel>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ListBox>
        </ScrollViewer>

推荐阅读