С# WPF(MVVM) Как взаимодействовать с DependencyProperty из ViewModel

88
24 ноября 2021, 01:20

Только недавно начал постигать паттерн MVVM, и столкнулся со следующим вопросом. Как правильно получить доступ к DependencyProperty из ViewModel. В классическом подходе с этим никаких проблем нет ибо все находится в code-behind, а вот MVVM подходе вообще не понятно что с этим делать. Например мы хотим собрать свой FilePicker у которого будет свойство FileName к которому в будущем можно будет привязаться.

View

<UserControl
    x:Class="Demo.FilePicker"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:localControls="clr-namespace:Demo.Controls"
    x:Name="filePickerControl">
    <UserControl.DataContext>
        <localControls:FilePickerViewModel />
    </UserControl.DataContext>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>
        <TextBox
            x:Name="fileNameTextBox"
            Grid.Column="0"
            IsReadOnly="True"
            Text="{Binding ElementName=filePickerControl, Path=FileName}" />
        <Button
            x:Name="browseFileButton"
            Grid.Column="1"
            Command="{Binding Path=BrowseCommand}"
            Content="Browse…" />
    </Grid>
</UserControl>

View code-behind

using System.Windows;
using System.Windows.Controls;
namespace Demo.Controls
{
    public partial class FilePicker : UserControl
    {
        public string FileName
        {
            get { return (string)GetValue(FileNameProperty); }
            set { SetValue(FileNameProperty, value); }
        }
        public static readonly DependencyProperty FileNameProperty =
            DependencyProperty.Register("FileName", typeof(string), typeof(FilePicker), new FrameworkPropertyMetadata() { BindsTwoWayByDefault = true });
        public FilePicker()
        {
            InitializeComponent();
        }
    }
}

ViewModel

using Microsoft.Win32;
using System.Windows;
namespace Demo.Controls
{
    class FilePickerViewModel : BindableBase
    {
        private string _fileName;
        public string FileName
        {
            get { return _fileName; }
            set 
            { 
                _fileName = value;
                OnPropertyChanged();
            }
        }
        private DelegateCommand _browseCommand;
        public DelegateCommand BrowseCommand =>
            _browseCommand ?? (_browseCommand = new DelegateCommand(ExecuteBrowseCommand));
        public FilePickerViewModel()
        {
        }
        void ExecuteBrowseCommand()
        {
            var openFileDialog = new OpenFileDialog();
            if (openFileDialog.ShowDialog() == true)
                FileName = openFileDialog.FileName;
            else
                FileName = null;
        }
    }
}

Как связать FileName из View и FileName из ViewModel в режиме TwoWay. Или как сразу получить доступ к свойству зависимости из ViewModel.

P.S. Я знаю что можно объявить DependencyProperty в ViewModel, но мне кажется что размазывать View по ViewModel, которая вообще о View знать не должна, это не лучшая идея.

READ ALSO
автообновление программы ClickOnce

автообновление программы ClickOnce

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

174
unity.system; Не работают ивенты

unity.system; Не работают ивенты

Есть две части кода:

77
Как упростить код включения/отключения компонентов через GetComponent

Как упростить код включения/отключения компонентов через GetComponent

Как проще и красивей записать следующий код :

218
Поток из консоли и с чем его едят

Поток из консоли и с чем его едят

Мне стало интересно, что именно происходит в данном коде:

116