Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WPF UserControl,带有按钮和键绑定_C#_Wpf_Xaml_User Controls_Key Bindings - Fatal编程技术网

C# WPF UserControl,带有按钮和键绑定

C# WPF UserControl,带有按钮和键绑定,c#,wpf,xaml,user-controls,key-bindings,C#,Wpf,Xaml,User Controls,Key Bindings,我正在尝试在WPF中实现一个拨号程序。我有一个窗口,里面有一个用户控件。用户控件有很多按钮,但用户也可以使用数字键盘输入数字 我创建了一个小样本项目,以显示我所处的位置: main window.xaml <Window x:Class="wpf_dialer.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schema

我正在尝试在WPF中实现一个拨号程序。我有一个窗口,里面有一个用户控件。用户控件有很多按钮,但用户也可以使用数字键盘输入数字

我创建了一个小样本项目,以显示我所处的位置:

main window.xaml

<Window x:Class="wpf_dialer.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:wpf_dialer"
        Title="MainWindow" Height="200" Width="525">
  <Window.Resources>
    <local:DialerViewModel x:Key="myViewModel" />
  </Window.Resources>
  <Grid DataContext="{StaticResource myViewModel}">
    <local:Dialer />
  </Grid>
</Window>
<UserControl x:Class="wpf_dialer.Dialer"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:wpf_dialer"
             mc:Ignorable="d" 
             d:DesignHeight="200" d:DesignWidth="300"
             d:DataContext="{d:DesignInstance local:DialerViewModel}"
             Loaded="UserControl_Loaded">
  <UserControl.InputBindings>
    <KeyBinding Key="A" Command="{Binding CommandDialValue, Mode=OneTime}" CommandParameter="." />
    <KeyBinding Key="Back" Command="{Binding CommandDialValue, Mode=OneTime}" CommandParameter="Back" />
    <KeyBinding Key="Enter" Command="{Binding  CommandAcceptValue, Mode=OneTime}" CommandParameter="KeyBinding" />
  </UserControl.InputBindings>
  <UniformGrid Columns="1">
    <TextBox IsEnabled="False" Text="{Binding DialedValue, Mode=OneWay}" MinWidth="200" FontSize="20" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="10"/>
    <Button Content="OK" Margin="60,30" Command="{Binding CommandAcceptValue, Mode=OneTime}" CommandParameter="Button" />
  </UniformGrid>
</UserControl>
             d:DataContext="{d:DesignInstance local:DialerViewModel}"
             Loaded="UserControl_Loaded" Focusable="True">
  <UserControl.InputBindings>

拨号器.xaml

<Window x:Class="wpf_dialer.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:wpf_dialer"
        Title="MainWindow" Height="200" Width="525">
  <Window.Resources>
    <local:DialerViewModel x:Key="myViewModel" />
  </Window.Resources>
  <Grid DataContext="{StaticResource myViewModel}">
    <local:Dialer />
  </Grid>
</Window>
<UserControl x:Class="wpf_dialer.Dialer"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:wpf_dialer"
             mc:Ignorable="d" 
             d:DesignHeight="200" d:DesignWidth="300"
             d:DataContext="{d:DesignInstance local:DialerViewModel}"
             Loaded="UserControl_Loaded">
  <UserControl.InputBindings>
    <KeyBinding Key="A" Command="{Binding CommandDialValue, Mode=OneTime}" CommandParameter="." />
    <KeyBinding Key="Back" Command="{Binding CommandDialValue, Mode=OneTime}" CommandParameter="Back" />
    <KeyBinding Key="Enter" Command="{Binding  CommandAcceptValue, Mode=OneTime}" CommandParameter="KeyBinding" />
  </UserControl.InputBindings>
  <UniformGrid Columns="1">
    <TextBox IsEnabled="False" Text="{Binding DialedValue, Mode=OneWay}" MinWidth="200" FontSize="20" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="10"/>
    <Button Content="OK" Margin="60,30" Command="{Binding CommandAcceptValue, Mode=OneTime}" CommandParameter="Button" />
  </UniformGrid>
</UserControl>
             d:DataContext="{d:DesignInstance local:DialerViewModel}"
             Loaded="UserControl_Loaded" Focusable="True">
  <UserControl.InputBindings>

拨号服务模型.cs

using System;
using System.ComponentModel;
using System.Windows.Input;

namespace wpf_dialer
{
    class DialerViewModel : INotifyPropertyChanged
    {
        private Random RAND = new Random();
        private string _dialed_value = "00";
        public string DialedValue
        {
            get { return _dialed_value; }
            set
            {
                if (_dialed_value == value) return;
                _dialed_value = value;
                RaisePropertyChanged("DialedValue");
            }
        }

        public ICommand CommandDialValue { get { return new CommandImpl(DialValue); } }
        public ICommand CommandAcceptValue { get { return new CommandImpl(Alert); } }

        private void DialValue(object parameter)
        {
            if (parameter.ToString() == "Back")
            {
                if (DialedValue.Length > 0)
                {
                    DialedValue = DialedValue.Substring(0, DialedValue.Length - 1);
                }
            }
            else
            {
                DialedValue += RAND.Next(0, 10).ToString();
            }
        }

        private void Alert(object parameter)
        {
            System.Windows.MessageBox.Show(parameter.ToString());
        }

        #region INotifyPropertyChanged

        protected void RaisePropertyChanged(string property_name)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(property_name));
            }
        }
        public event PropertyChangedEventHandler PropertyChanged;
        #endregion

        private class CommandImpl : ICommand
        {
            private readonly Action<object> _action = null;
            public CommandImpl(Action<object> action)
            {
                _action = action;
            }

            public event EventHandler CanExecuteChanged;
            public bool CanExecute(object parameter) { return true; }
            public void Execute(object parameter) { _action(parameter); }
        }
    }
}
private void UserControl_Loaded(object sender, RoutedEventArgs e) {
    Focus();
}
使用系统;
使用系统组件模型;
使用System.Windows.Input;
名称空间wpf_拨号器
{
类DialServiceWModel:INotifyPropertyChanged
{
private Random RAND=new Random();
私人字符串_dialed_value=“00”;
公共字符串拨号值
{
获取{return\u dialled\u value;}
设置
{
如果(_拨号_值==值)返回;
_拨出的值=值;
RaisePropertyChanged(“DialledValue”);
}
}
public ICommand CommandDialValue{get{返回新CommandImpl(DialValue);}
public ICommand CommandAcceptValue{get{return new CommandImpl(Alert);}
私有值(对象参数)
{
if(parameter.ToString()=“Back”)
{
如果(DialledValue.Length>0)
{
dialledvalue=dialledvalue.Substring(0,dialledvalue.Length-1);
}
}
其他的
{
dialledvalue+=RAND.Next(0,10).ToString();
}
}
私有无效警报(对象参数)
{
System.Windows.MessageBox.Show(parameter.ToString());
}
#区域inotifyproperty已更改
受保护的void RaisePropertyChanged(字符串属性\u名称)
{
if(PropertyChanged!=null)
{
PropertyChanged(这是新PropertyChangedEventArgs(property_name));
}
}
公共事件属性更改事件处理程序属性更改;
#端区
私有类CommandImpl:ICommand
{
私有只读操作_Action=null;
公共命令impl(操作)
{
_行动=行动;
}
公共事件处理程序CanExecuteChanged;
public bool CanExecute(对象参数){return true;}
public void Execute(对象参数){u action(参数);}
}
}
}
目标:

  • 一旦加载窗口,当用户按下A键时,执行命令拨号值
  • 当用户按Enter键时,将显示一个消息框,文本为“KeyBinding”。CommandAcceptValue必须从KeyBinding调用,而不是从按钮调用
问题:

  • 加载窗口时,不会执行键绑定。当我单击UserControl中的某个按钮时,它们被执行

  • 当我按下Enter键时,按钮的命令被执行,但我希望用户控件的键绑定被执行

  • 此拨号程序必须保存在UserControl(或ControlTemplate,或DataTemplate)中,因为它包含在一个非常复杂的窗口中

  • 我不想将KeyBindings放在窗口上,因为UserControl是不可重用的,而且它的DataContext与用户控件不同

更新:


我通过在所有按钮上设置
Focusable=“False”
解决了第二个问题。

这是一个焦点问题。首次加载窗口时,用户控件没有焦点。所以键绑定的手势不会截获你的按键。在第一次加载应用程序时,您必须关注您的用户控制。(Focusable=“True”(我不知道这是否有帮助,但我相信这会有所帮助)。然后你的按键手势就会很好地工作。

为了防止按钮获得焦点,我为所有按钮设置了
Focusable=“False”

要在窗口打开时设置焦点,我在UserControl上设置了
Focusable=“True”
,并在加载的事件上设置了
focus()

拨号器.xaml

<Window x:Class="wpf_dialer.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:wpf_dialer"
        Title="MainWindow" Height="200" Width="525">
  <Window.Resources>
    <local:DialerViewModel x:Key="myViewModel" />
  </Window.Resources>
  <Grid DataContext="{StaticResource myViewModel}">
    <local:Dialer />
  </Grid>
</Window>
<UserControl x:Class="wpf_dialer.Dialer"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:wpf_dialer"
             mc:Ignorable="d" 
             d:DesignHeight="200" d:DesignWidth="300"
             d:DataContext="{d:DesignInstance local:DialerViewModel}"
             Loaded="UserControl_Loaded">
  <UserControl.InputBindings>
    <KeyBinding Key="A" Command="{Binding CommandDialValue, Mode=OneTime}" CommandParameter="." />
    <KeyBinding Key="Back" Command="{Binding CommandDialValue, Mode=OneTime}" CommandParameter="Back" />
    <KeyBinding Key="Enter" Command="{Binding  CommandAcceptValue, Mode=OneTime}" CommandParameter="KeyBinding" />
  </UserControl.InputBindings>
  <UniformGrid Columns="1">
    <TextBox IsEnabled="False" Text="{Binding DialedValue, Mode=OneWay}" MinWidth="200" FontSize="20" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="10"/>
    <Button Content="OK" Margin="60,30" Command="{Binding CommandAcceptValue, Mode=OneTime}" CommandParameter="Button" />
  </UniformGrid>
</UserControl>
             d:DataContext="{d:DesignInstance local:DialerViewModel}"
             Loaded="UserControl_Loaded" Focusable="True">
  <UserControl.InputBindings>

我没有发现有效的
FocusManager.FocusedElement
组合。我尝试了
{Binding ElementName=myUserControl}
,和
{Binding RelativeSource={RelativeSource Self}

你能更精确一点吗?我在UserControl上尝试了
FocusManager.FocusedElement=“{Binding RelativeSource={RelativeSource Mode=Self}}”
,但没有帮助。给你一个X:Name属性=CustomName,然后给你一个FocusManager.FocusedElement=“{Binding ElementName=CustomName}