注意:我不确定该怎么称呼此问题,但它与取消绑定/重新绑定属性有关。
我有一个用编码器控制电机的arduino。我想创建一个接口来控制它,同时读取它的位置(使用编码器)。
观点: 我有一个文本框来显示电机位置的数字读数(DRO)。它的Text属性绑定到ViewModel的公共属性。
我希望能够在看到DRO的同时向Arduino发送所需的位置。换句话说,TextBox应该不断输出电机的位置,但是一旦我开始输入一个值,就把这个值发送给Arduino(有一些格式,所以Arduino知道如何处理它)。
现在正在发生的事情是,我有一个串行数据接收事件处理程序,它获取电机位置并将其设置为绑定属性,然后将其显示在文本框中。我需要知道一种方法,当它具有Focus时暂时禁用文本框的绑定。然后它需要在失去焦点后重新绑定。
有没有办法禁用控件的绑定,然后在事件后重新启用绑定?这是解决此问题的最佳方法吗?
感谢您的帮助!
答案 0 :(得分:1)
不是禁用绑定(不确定如何),而是在将值从Arduino发送到UI之前添加条件。我建议您尝试使用此SO answer中的IsFocused
属性。
FocusExtension:
public static class FocusExtension
{
public static bool GetIsFocused(DependencyObject obj)
{
return (bool) obj.GetValue(IsFocusedProperty);
}
public static void SetIsFocused(DependencyObject obj, bool value)
{
obj.SetValue(IsFocusedProperty, value);
}
public static readonly DependencyProperty IsFocusedProperty =
DependencyProperty.RegisterAttached(
"IsFocused", typeof (bool), typeof (FocusExtension),
new UIPropertyMetadata(false, OnIsFocusedPropertyChanged));
private static void OnIsFocusedPropertyChanged(
DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
var uie = (UIElement) d;
if ((bool) e.NewValue)
{
uie.Focus(); // Don't care about false values.
}
}
}
用法:
<TextBox local:FocusExtension.IsFocused="{Binding IsDigitalReadOutFocused}" />
为视图模型创建一种方法,以了解控件是否已被聚焦。
public class ViewModel : ObservableBase // Made this up. It should implement INotifyPropertyChanged
{
private bool _isDROFocused { get; set; }
public bool IsDigitalReadOutFocused
{
get { return this._isDROFocused; }
set
{
this._isDROFocused = value;
OnPropertyChanged("IsDigitalReadOutFocused");
}
}
// On your Serial Data Received event handler
//if(!IsDigitalReadOutFocused)
//{
// DigitalReadOut = somevalue; // Set the textbox value
//}
}
答案 1 :(得分:0)
如果我理解你可能需要触发文本框并使用bool值绑定触发器。 这是按钮触发器的示例
<Style>
<Setter Property="Content" Value="Scream" />
<Style.Triggers>
<DataTrigger Binding="{Binding btnEnabled}" Value="True">
<Setter Property="IsEnabled" Value="True" />
</DataTrigger>
</Style.Triggers>
</Style>
答案 2 :(得分:0)
有没有办法禁用控件的绑定,然后在事件后重新启用绑定?
你不能&#34;禁用&#34;绑定,但您可以使用BindingOperations.ClearBinding
方法以编程方式删除绑定,并且可以使用BindingOperations.SetBinding
方法以编程方式创建绑定。
<强> XAML:强>
<TextBox x:Name="textBox" GotKeyboardFocus="textBox_GotKeyboardFocus" LostKeyboardFocus="textBox_LostKeyboardFocus" />
示例代码:
private void textBox_GotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
BindingOperations.ClearBinding(textBox, TextBox.TextProperty);
}
private void textBox_LostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
BindingOperations.SetBinding(textBox, TextBox.TextProperty, new Binding("ThePropertyToBindTo"));
}
答案 3 :(得分:0)
我将使用我在StackOverflow周围找到的详细信息来回答我的问题。
首先,我需要处理GotFocus和LostFocus事件。我不想使用Code Behind,所以我发现我可以使用System.Windows.Interactivity.dll参考中的Interactivity。 (来自THIS文章)
视图模型:
using System.Windows.Interactivity;
private bool _xFocus;
public ICommand XGotFocus { get; set; }
public ICommand XLostFocus { get; set; }
public ICommand XSend { get; set; }
// In the constructor:
XGotFocus = new RelayCommand(() => _xFocus = true);
XLostFocus = new RelayCommand(() => _xFocus = false);
XSend = new RelayCommand(() => ExecuteXSend());
// Done with constructor
private void ExecuteXSend()
{
RaisePropertyChanged("Xdro");
string sendToPort = "X" + Xdro;
try
{
port.WriteLine(sendToPort);
}
catch (Exception ex)
{
MessageBox.Show("Error: \r\r" + ex.Message);
}
Console.WriteLine("Sending X position: " + sendToPort);
MotorsMoving = true;
RaisePropertyChanged("MotorsMoving");
}
查看:
<TextBox x:Name="tbXDro" HorizontalAlignment="Center" VerticalAlignment="Center" Width="75" IsReadOnly="False" FontSize="11" MaxLines="1" Text="{Binding Xdro, UpdateSourceTrigger=PropertyChanged}" local:InputBindingsManager.UpdatePropertySourceWhenEnterPressed="TextBox.Text">
<i:Interaction.Triggers>
<i:EventTrigger EventName="GotFocus">
<i:InvokeCommandAction Command="{Binding XGotFocus, Mode=OneWay}"/>
</i:EventTrigger>
<i:EventTrigger EventName="LostFocus">
<i:InvokeCommandAction Command="{Binding XLostFocus, Mode=OneWay}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<TextBox.InputBindings>
<KeyBinding Command="{Binding XSend}" Key="Return"/>
</TextBox.InputBindings>
</TextBox>
正如您所看到的,我对命令的返回键有一个键绑定&#34; XSend&#34;。为了更新Xdro属性,THIS文章介绍了在按下回车键时更新属性的方法。
InputBindingsManager.cs
public static class InputBindingsManager
{
public static readonly DependencyProperty UpdatePropertySourceWhenEnterPressedProperty = DependencyProperty.RegisterAttached(
"UpdatePropertySourceWhenEnterPressed", typeof(DependencyProperty), typeof(InputBindingsManager), new PropertyMetadata(null, OnUpdatePropertySourceWhenEnterPressedPropertyChanged));
static InputBindingsManager()
{
}
public static void SetUpdatePropertySourceWhenEnterPressed(DependencyObject dp, DependencyProperty value)
{
dp.SetValue(UpdatePropertySourceWhenEnterPressedProperty, value);
}
public static DependencyProperty GetUpdatePropertySourceWhenEnterPressed(DependencyObject dp)
{
return (DependencyProperty)dp.GetValue(UpdatePropertySourceWhenEnterPressedProperty);
}
private static void OnUpdatePropertySourceWhenEnterPressedPropertyChanged(DependencyObject dp, DependencyPropertyChangedEventArgs e)
{
UIElement element = dp as UIElement;
if (element == null)
{
return;
}
if (e.OldValue != null)
{
element.PreviewKeyDown -= HandlePreviewKeyDown;
}
if (e.NewValue != null)
{
element.PreviewKeyDown += new KeyEventHandler(HandlePreviewKeyDown);
}
}
static void HandlePreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
DoUpdateSource(e.Source);
}
}
static void DoUpdateSource(object source)
{
DependencyProperty property =
GetUpdatePropertySourceWhenEnterPressed(source as DependencyObject);
if (property == null)
{
return;
}
UIElement elt = source as UIElement;
if (elt == null)
{
return;
}
BindingExpression binding = BindingOperations.GetBindingExpression(elt, property);
if (binding != null)
{
binding.UpdateSource();
}
}
}
所有这一切都实现了目标:
感谢所有人的帮助!