WPF UserControls: имейте команду, которая доступна только внутри UserControl.

Я делаю WPF UserControl.

Внутри этого UserControl есть несколько Button, которые можно использовать при определенных условиях, так что привязка их к команде идеальна.

Команда, вызываемая этими кнопками, не должна быть доступна за пределами UserControl.

Если я сделаю свои команды закрытыми, XAML UserControl говорит, что ему нужен открытый член.

Итак, как же получить один UserControl, который имеет несколько команд внутри, но недоступен за пределами UserControl?

Пример:

<Wizard CanGoPrevious="{Binding SomeViewModelProperty}">
    <WizardPage>
        <TextBlock>Page one</TextBlock>
    </WizardPage>
</Wizard>

XAML мастера:

<DockPanel DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type wizard:Wizard}}}" LastChildFill="True">
    <StackPanel Orientation="Horizontal" DockPanel.Dock="Bottom" HorizontalAlignment="Right"> 
        <Button Content="{Binding PreviousButtonText}" Command="{Binding GoToPreviousPageCommand}"/>
    </StackPanel>
    <ContentControl ></ContentControl>
</DockPanel>

Код волшебника позади:

//Protected doesn't work. Also, this command should not be available outside of the Wizard `UserControl`
protected DelegateCommand GoToPreviousPageCommand { get; set; } 

Что назначается так в конструкторе

GoToPreviousPageCommand = new DelegateCommand(GoToPreviousPage, CanGoToPreviousPage);


    private void GoToPreviousPage()
    {
        //[...]
    }

    private bool CanGoToNextPage()
    {
        //Some usage of the Wizard's DP:
        return CanGoPrevious //&& some other stuff
    }

Не беспокойся. Это пользовательский элемент управления — вполне нормально включать логику, относящуюся к пользовательскому интерфейсу, в программный код.   —  person J4N    schedule 04.09.2015

@Will Хорошо, но не удается предоставить UserControl общедоступный доступ к командам, которые должны быть доступны только для внутреннего использования.   —  person J4N    schedule 04.09.2015

См. также:  Невозможно создать событие для локальных объектов в гибридной среде с помощью Graph API
Понравилась статья? Поделиться с друзьями:
IT Шеф
Комментарии: 1
  1. J4N

    РЕДАКТИРОВАТЬ: добавление образца кода (должна иметь возможность копировать / вставлять / запускать): оставьте команду общедоступной, но сделайте внутреннюю модель ViewModel невидимой для внешнего кода!

    <Window x:Class="InternalCommandUsageSample.MainWindow"
        xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:InternalCommandUsageSample"
        Title="MainWindow" Height="350" Width="525">
    <local:MyUserControl/>
    

    code behind the window that tests user control:

    using System.Windows;
    
    namespace InternalCommandUsageSample
    {
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            var vm = new MyViewModel();
            DataContext = vm;
    
            InitializeComponent();
        }
    }
    

    }

    пользовательский контроль:

    <UserControl x:Class="InternalCommandUsageSample.MyUserControl"
             xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml">
    <StackPanel>
        <TextBlock Text="{Binding Message, Mode=OneWay}"/>
        <Button Content="Test Me" Command="{Binding TestMeCommand}"/>
    </StackPanel>
    

    and the internal view model that is not visible outside your assembly:

    internal class MyViewModel : INotifyPropertyChanged
    {
        private string _message = "click the button";
        private DelegateCommand _cmd;
    
        public DelegateCommand TestMeCommand
        {
            get
            {
                return _cmd ?? (_cmd = new DelegateCommand(cmd => { Message = "Your button click envoked an internal command"; }));
            }
        }
    
        public string Message
        {
            get { return _message; }
            set
            {
                if (_message != value)
                {
                    _message = value;
                    OnPropertyChanged("Message");
                }
            }
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
    
        protected virtual void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    

    РЕДАКТИРОВАТЬ: в комментариях был задан дополнительный вопрос о том, как использовать свойство зависимости элемента управления suer и модели представления. Есть много способов, это один из них:

            public string MySampleDependencyProperty
        {
            get { return (string)GetValue(MySampleDependencyPropertyProperty); }
            set { SetValue(MySampleDependencyPropertyProperty, value); }
        }
    
        public static readonly DependencyProperty MySampleDependencyPropertyProperty = 
            DependencyProperty.Register("MySampleDependencyProperty", typeof(string), 
            typeof(MyUserControl),
            new FrameworkPropertyMetadata("", 
                FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, (o, e) => ((MyUserControl)o).OnMySampleDependencyPropertyChanged()));
    
        private void OnMySampleDependencyPropertyChanged()
        {
            viewMdoel.WhateverProperty = MySampleDependencyProperty;
        }
    

    Хорошо, это означает, что это можно редактировать из библиотеки, но это приемлемо. Изначально я хотел создать ViewModel, но у меня не было ощущения, что это возможно с DependencyProperties, я ошибаюсь? person J4N; 04.09.2015

    опубликуйте немного своего кода, чтобы я мог понять, о чем вы говорите. Поскольку с ViewModel вам не нужны свойства зависимостей, вы можете иметь обычные свойства, если они вызывают событие propertyChanged. Также команда может (или обычно) иметь частный установщик, поэтому ее нельзя редактировать. person J4N; 04.09.2015

    Какую часть кода вы хотите увидеть? Дело в том, что в окнах, где мы будем использовать этот UserControl, некоторые свойства (UserControl) будут привязаны к свойствам ViewModel MainWindow. И в моем UserControl мне нужны некоторые значения этих связанных значений person J4N; 04.09.2015

    Я добавил код. Кроме того, я попытался сделать команду внутренней, но похоже, что Visual Studio все еще недовольна. VS сообщает мне, что ожидается член Public, и если я его запустил, то получу ошибку пути BindingExpression. person J4N; 04.09.2015

    Я напечатаю что-нибудь здесь через немного person J4N; 04.09.2015

    Я добавил код, который вы должны уметь запускать, он очень прост и должен дать вам представление о том, как создать пользовательский элемент управления и по-прежнему использовать MVVM без раскрытия внутренней логики, которой вы не хотите делиться с пользователями, хорошо удача person J4N; 04.09.2015

    Спасибо, кажется неплохим, но у меня все еще один вопрос: мой UserControl должен иметь некоторые свойства зависимостей, как заставить их работать с вашей ViewModel? person J4N; 04.09.2015

    извините, долгие выходные, только что посмотрели ваше сообщение и добавили для вас больше примеров кода по вашему последнему вопросу person J4N; 08.09.2015

Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: