繁体   English   中英

将WPF命令绑定到C#XAML中的ViewModel属性

[英]Bind WPF Command to ViewModel property in C# XAML

我正在尝试构建一个通用Command ,该Command可以从ViewModel访问属性。 在我的窗口上有几个TextBoxes ,每个TextBox旁边都有一个Button Button被点击我表现出OpenFileDialog和设置Text中的TextBox到选定的文件路径。 TextBox本身具有对ViewModel的属性的Binding 当前,这是通过ViewModelCommand实现的。 Buttons都调用相同的Command但是每个Button的属性CommandParameter设置为TextBox ,它将接收文件路径。 这样做的缺点是,我需要将Command执行中的参数强制转换为TextBox ,然后设置其Text属性。 现在的问题是,如果我不能以某种方式将“命令”绑定到TextBox绑定到的同一属性。 这是我目前正在做的事情:

XAML

<TextBox Text="{Binding SettingsPath}" x:Name="txtSettingsPath"></TextBox>
<Button Command="{Binding OpenFile}" 
CommandParameter="{Binding ElementName=txtSettingsPath}">...</Button>

C#

public ICommand OpenFile
{
    get
    {
        bool CanExecuteOpenFileCommand()
        {
            return true;
        }

        CommandHandler GetOpenFileCommand()
        {
            return new CommandHandler((o) =>
            {
                OpenFileDialog ofd = new OpenFileDialog();
                ofd.Multiselect = false;

                if (!string.IsNullOrEmpty(SettingsPath) && File.Exists(settingsPath))
                {
                    ofd.InitialDirectory = Path.GetDirectoryName(SettingsPath);
                }

                if(ofd.ShowDialog() == true)
                {
                    if(o is TextBox txt)
                    {
                        txt.Text = ofd.FileName;
                    }
                }

            }, CanExecuteOpenFileCommand);
        }

        return GetOpenFileCommand();
    }
}

在XAML中,我想要这样的东西:

<TextBox Text="{Binding SettingsPath}"></TextBox>
<Button Command="{Binding OpenFile}" 
CommandParameter="{Binding SettingsPath}">...</Button>

这是我在评论中谈论的内容:

“小视图模型”。 我添加了Label属性,因为在我的测试项目中,它们看起来都一样。 那不一定是这个视图模型的一部分。

public class SettingsPathSelectorViewModel : ViewModelBase
{
    #region Label Property
    private String _label = default(String);
    public String Label
    {
        get { return _label; }
        set
        {
            if (value != _label)
            {
                _label = value;
                OnPropertyChanged();
            }
        }
    }
    #endregion Label Property

    #region SettingsPath Property
    private String _settingsPath = null;
    public String SettingsPath
    {
        get { return _settingsPath; }
        set
        {
            if (value != _settingsPath)
            {
                _settingsPath = value;
                OnPropertyChanged();
            }
        }
    }
    #endregion SettingsPath Property


    public ICommand OpenFile
    {
        get
        {
            bool CanExecuteOpenFileCommand()
            {
                return true;
            }

            //  We're no longer using the parameter, since we now have one                 
            //  command per SettingsPath. 
            CommandHandler GetOpenFileCommand()
            {
                return new CommandHandler((o) =>
                {
                    OpenFileDialog ofd = new OpenFileDialog();
                    ofd.Multiselect = false;

                    if (!string.IsNullOrEmpty(SettingsPath) && System.IO.File.Exists(SettingsPath))
                    {
                        ofd.InitialDirectory = System.IO.Path.GetDirectoryName(SettingsPath);
                    }

                    if (ofd.ShowDialog() == true)
                    {
                        SettingsPath = ofd.FileName;
                    }
                }, o => CanExecuteOpenFileCommand());
            }

            return GetOpenFileCommand();
        }
    }
}

用于演示目的的快速主视图模型。 我们将说明两种公开这些内容的方法:作为命名属性,或在ItemsControl显示的各种大小的集合。

public class MainViewModel : ViewModelBase
{
    public SettingsPathSelectorViewModel FirstPath { get; } = new SettingsPathSelectorViewModel() { Label = "First Path" };
    public SettingsPathSelectorViewModel SecondPath { get; } = new SettingsPathSelectorViewModel() { Label = "Second Path" };

    public ObservableCollection<SettingsPathSelectorViewModel> SettingsPaths { get; } = new ObservableCollection<SettingsPathSelectorViewModel>
    {
        new SettingsPathSelectorViewModel() { Label = "First Collection Path" },
        new SettingsPathSelectorViewModel() { Label = "Second Collection Path" },
        new SettingsPathSelectorViewModel() { Label = "Third Collection Path" },
    };
}

XAML:

<Window.Resources>
    <DataTemplate DataType="{x:Type local:SettingsPathSelectorViewModel}">
        <!-- GroupBox and Label are optional -->
        <GroupBox Header="{Binding Label}">
            <StackPanel Orientation="Horizontal">
                <TextBox Text="{Binding SettingsPath}" />
                <Button 
                    Content="..." 
                    Command="{Binding OpenFile}" 
                    HorizontalAlignment="Left" 
                    MinWidth="40" 
                    Margin="4,0,0,0" 
                    />
            </StackPanel>
        </GroupBox>
    </DataTemplate>
</Window.Resources>
<Grid>
    <StackPanel Orientation="Vertical">
        <StackPanel Orientation="Horizontal">
            <ContentControl Content="{Binding FirstPath}" />
            <ContentControl Content="{Binding SecondPath}" />
        </StackPanel>
        <ItemsControl
            ItemsSource="{Binding SettingsPaths}"
            />
    </StackPanel>
</Grid>

这就是我省略LabelGroupBox

<Window.Resources>
    <DataTemplate DataType="{x:Type local:SettingsPathSelectorViewModel}">
        <StackPanel Orientation="Horizontal">
            <TextBox Text="{Binding SettingsPath}" />
            <Button 
                Content="..." 
                Command="{Binding OpenFile}" 
                HorizontalAlignment="Left" 
                MinWidth="40" 
                Margin="4,0,0,0" 
                />
        </StackPanel>
    </DataTemplate>
</Window.Resources>
<Grid>
    <StackPanel Orientation="Vertical">
        <Label>First Path</Label>
        <ContentControl Content="{Binding FirstPath}" />
        <Label>Second Path</Label>
        <ContentControl Content="{Binding SecondPath}" />
    </StackPanel>
</Grid>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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