简体   繁体   中英

Notifying that a RadioButton has been selected in a UserControl in WPF

I am trying to make a button in a viewmodel recognize that a radio button in another view model (a UserControl that is activated on the first viewmodel) has been selected, thus enabling the button in the first viewmodel. I have a UserControl AlbumsDisplayViewModel within my base view model BaseViewModel . In BaseView XAML There's a button (OpenAlbum) which is supposed to be enabled when a radio button on the AlbumsDisplayView is selected (see CanOpenAlbum).

BaseView 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)*/);
        }
}

AlbumsDisplayView 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>

AlbumsDisplayViewModel 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;
        }
    }

And last, 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);
            }
        }
   }

I expected that when IsSelected in AlbumViewModel is changed (when the user selects a radio button), the OpenAlbum button will be enabled, because CanOpenAlbum will return true, but I have realized that CanOpenAlbum wasn't even called for some reason. What do I need to do so CanOpenAlbum will be notified to be called whenever a radio button is selected?

After searching for an answer for a long time, I decided that it will be better to search for a better solution, instead of an answer. I've discovered that a ListBox element has a SelectedItem property, which eliminates the need for radio buttons. Eventually, I replaced the ItemsControl with a ListBox, and I;m happy with the results.

AlbumDisplayView XAML (only this has changed):

<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>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM