WPF用户控件绑定问题 [英] WPF User control binding issue

查看:301
本文介绍了WPF用户控件绑定问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这应该是一个非常简单的例子,但我揪头发设法得到它的工作。下面是设置:

我设计一个应用程序,将有一些数据的只读模式和编辑模式。所以,我创建了一个用户控件是一个文本框和文本块绑定到相同的文本数据和有条件可见基于EditableMode财产(所以当它的可编辑显示的文本框,当它不是文本块所示)

现在,我想有很多这些控制在我的主窗口,并让他们所有绑定过于单一的布尔属性。当该属性通过一个按钮改变,我希望所有的TextBlocks变成文本框或背部。

我的问题是,控制设置正确的约束力,如果我做myUserControl.Editable = TRUE。但它并没有改变,如果将其绑定到一个布尔属性。

下面是code为我的用户控件:

 <用户控件X:类=CustomerCareTool.Controls.EditableLabelControl
的xmlns =htt​​p://schemas.microsoft.com/winfx/2006/xaml/$p$psentation
的xmlns:X =htt​​p://schemas.microsoft.com/winfx/2006/xaml
的xmlns:SRC =CLR的命名空间:CustomerCareTool.Converters
的DataContext ={绑定的RelativeSource = {自我的RelativeSource}}>
< UserControl.Resources>
    < SRC:BoolToVisibility X:键=boolToVisibility反向=FALSE/>
    < SRC:BoolToVisibility X:键=invertedBoolToVisibility反向=真/>
< /UserControl.Resources>
<网格和GT;
    < TextBlock的名称=TextBlock的文本={绑定路径= TextBoxValue}能见度={绑定路径= EditableMode,转换器= {StaticResource的invertedBoolToVisibility}}/>
    <文本框名称=的textBox能见度={绑定路径= EditableMode,转换器= {StaticResource的boolToVisibility}}>
        < TextBox.Text>
            <绑定路径=TextBoxValueUpdateSourceTrigger =的PropertyChanged/>
        < /TextBox.Text>
    < /文本框>
< /网格和GT;

我用了一个转换器转换成布尔能见度和逆布尔能见度。不知道如果这是在所有需要在这里。

这背后是code:

 公共部分类EditableLabelControl:用户控件
{
    公共EditableLabelControl()
    {
        的InitializeComponent();
    }    公共字符串TextBoxValue
    {
        {返回(串)的GetValue(TextBoxValueProperty); }
        集合{的SetValue(TextBoxValueProperty,值); }
    }    公共静态只读的DependencyProperty TextBoxValueProperty =
        DependencyProperty.Register(TextBoxValue的typeof(串)的typeof(EditableLabelControl),新UIPropertyMetadata());
    公共BOOL EditableMode
    {
        {返回(布尔)的GetValue(EditableModeProperty); }
        集合{的SetValue(EditableModeProperty,值); }
    }    公共静态只读的DependencyProperty EditableModeProperty =
        DependencyProperty.Register(EditableMode的typeof(布尔)的typeof(EditableLabelControl),新UIPropertyMetadata(假,EditableModePropertyCallBack));静态无效EditableModePropertyCallBack(DependencyObject的财产,
DependencyPropertyChangedEventArgs参数)
    {
        VAR editableLabelControl =(EditableLabelControl)财产;
        VAR编辑模式=(布尔)args.NewValue;        如果(编辑模式)
        {
            editableLabelControl.textBox.Visibility = Visibility.Visible;
            editableLabelControl.textBlock.Visibility = Visibility.Collapsed;
        }
        其他
        {
            editableLabelControl.textBox.Visibility = Visibility.Collapsed;
            editableLabelControl.textBlock.Visibility = Visibility.Visible;
        }
    }
}

现在在我的主要应用我有添加了控制是这样的:

 <控制:EditableLabelControl X:NAME =testCtrlEditableMode ={绑定路径=编辑}TextBoxValue =约翰·史密斯Grid.Row =0/>

对于同一应用程序的DataContext设置自

 的DataContext ={绑定的RelativeSource = {自我的RelativeSource}}

而code的背后是这样的:

 公共部分类OrderInfoView:窗口,INotifyPropertyChanged的{
    公共OrderInfoView()
    {
        的InitializeComponent();
    }    私人无效Button_Click_1(对象发件人,RoutedEventArgs E)
    {
        可编辑=编辑!;
    }    私人布尔_editable = FALSE;
    公共BOOL编辑
    {
        得到
        {
            返回_editable;
        }
        组
        {
            _editable =价值;
            OnPropertyChanged(编辑);
        }
    }    受保护的虚拟无效OnPropertyChanged(字符串propertyName的)
    {
        如果(的PropertyChanged == NULL)回报;        的PropertyChanged(这一点,新PropertyChangedEventArgs(propertyName的));
    }
    公共事件PropertyChangedEventHandler的PropertyChanged;
}

单击该按钮不会做任何事情:(我想尽一切办法得到这个工作,并没有骰子。真的AP preciate一些帮助!


我尝试了以下内容,仍然无法正常工作:

 公共BOOL编辑
    {
        {返回(布尔)的GetValue(EditableProperty); }
        集合{的SetValue(EditableProperty,值); }
    }    公共静态只读的DependencyProperty EditableProperty =
        DependencyProperty.Register(可编辑的typeof(布尔)的typeof(OrderInfoView),新UIPropertyMetadata(假));


解决方案

它看起来像你的解决方案可能会比必要的更加复杂。如果你想要做的是有一个残疾文本框看起来像一个TextBlock的,那么你可以使用触发器和模板做到这一点。然后你可以应用样式的所有文本框。

下面就是这种做法的一个例子:

 <窗​​口x:类=WpfApplication25.Window1
        的xmlns =htt​​p://schemas.microsoft.com/winfx/2006/xaml/$p$psentation
        的xmlns:X =htt​​p://schemas.microsoft.com/winfx/2006/xaml
        标题=窗口1
        HEIGHT =300
        WIDTH =300
        >    < Window.Resources>        <! - 禁用文本框样式 - >
        <风格X:键=_ DisableTextBoxStyle的TargetType =文本框>
            < Style.Triggers>
                <触发属性=IsEnabledVALUE =FALSE>
                    < setter属性=模板>
                        < Setter.Value>
                            <的ControlTemplate的TargetType =文本框>
                                <! -
                                一定要申请之间的所有必要TemplateBindings
                                文本框和TextBlock的模板。
                                 - >
                                < TextBlock的文本={TemplateBinding文字}
                                           的FontFamily ={TemplateBinding的FontFamily}
                                           />
                            < /控件模板>
                        < /Setter.Value>
                    < /二传手>
                < /触发>
            < /Style.Triggers>
        < /样式和GT;    < /Window.Resources>    <&StackPanel的GT;
        <文本框IsEnabled ={结合器isChecked,的ElementName = uiIsEnabled}
                 风格={StaticResource的_DisableTextBoxStyle}
                 />        <切换按钮X:NAME =uiIsEnabledCONTENT =启用=器isChecked真/>
    < / StackPanel的>
< /窗GT;

This should be a very simple case, but I am pulling hair trying to get it to work. Here is the setup:

I am designing an app that will have an read-only mode and edit mode for some data. So I created a User Control which is a textbox and textblock bound to the same text data and are conditionally visible based on EditableMode property (so when it's editable the textbox is shown and when it's not the textblock is shown)

Now, I want to have many of these controls in my main window and have them all bound too a single bool property. When that property is changed via a button, I want all TextBlocks to turn into TextBoxes or back.

My problem is that the control is set correctly on binding, and if I do myUserControl.Editable = true. But it doesn't change if bind it to a bool property.

Here is the code for my user control:

<UserControl x:Class="CustomerCareTool.Controls.EditableLabelControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:src="clr-namespace:CustomerCareTool.Converters"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<UserControl.Resources>
    <src:BoolToVisibility x:Key="boolToVisibility" Inverted="False" />
    <src:BoolToVisibility x:Key="invertedBoolToVisibility" Inverted="True" />
</UserControl.Resources>
<Grid>
    <TextBlock Name="textBlock" Text="{Binding Path=TextBoxValue}" Visibility="{Binding Path=EditableMode, Converter={StaticResource invertedBoolToVisibility}}"/>
    <TextBox Name="textBox" Visibility="{Binding Path=EditableMode, Converter={StaticResource boolToVisibility}}">
        <TextBox.Text>
            <Binding Path="TextBoxValue" UpdateSourceTrigger="PropertyChanged"/>
        </TextBox.Text>
    </TextBox>
</Grid>

I used a converter to convert bool to visibility and inverse bool to visibility. Not sure if that's at all needed here.

And this is the code behind:

public partial class EditableLabelControl : UserControl
{
    public EditableLabelControl()
    {
        InitializeComponent();
    }

    public string TextBoxValue
    {
        get { return (string)GetValue(TextBoxValueProperty); }
        set { SetValue(TextBoxValueProperty, value); }
    }

    public static readonly DependencyProperty TextBoxValueProperty =
        DependencyProperty.Register("TextBoxValue", typeof(string), typeof(EditableLabelControl), new UIPropertyMetadata());


    public bool EditableMode
    {
        get { return (bool)GetValue(EditableModeProperty); }
        set { SetValue(EditableModeProperty, value); }
    }

    public static readonly DependencyProperty EditableModeProperty =
        DependencyProperty.Register("EditableMode", typeof(bool),typeof(EditableLabelControl), new UIPropertyMetadata(false, EditableModePropertyCallBack));

static void EditableModePropertyCallBack(DependencyObject property,
DependencyPropertyChangedEventArgs args)
    {
        var editableLabelControl = (EditableLabelControl)property;
        var editMode = (bool)args.NewValue;

        if (editMode)
        {
            editableLabelControl.textBox.Visibility = Visibility.Visible;
            editableLabelControl.textBlock.Visibility = Visibility.Collapsed;
        }
        else
        {
            editableLabelControl.textBox.Visibility = Visibility.Collapsed;
            editableLabelControl.textBlock.Visibility = Visibility.Visible; 
        }
    }
}

Now in my main application I have the control added like this:

<Controls:EditableLabelControl x:Name="testCtrl" EditableMode="{Binding Path=Editable}" TextBoxValue="John Smith" Grid.Row="0"/>

For that same application the DataContext is set to self

DataContext="{Binding RelativeSource={RelativeSource Self}}"

And the code behind looks like this:

public partial class OrderInfoView : Window, INotifyPropertyChanged

{
    public OrderInfoView()
    {
        InitializeComponent();
    }

    private void Button_Click_1(object sender, RoutedEventArgs e)
    {
        Editable = !Editable;
    }

    private bool _editable = false;
    public bool Editable
    {
        get
        {
            return _editable;
        }
        set
        {
            _editable = value;
            OnPropertyChanged("Editable");
        }
    }

    protected virtual void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged == null) return;

        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }


    public event PropertyChangedEventHandler PropertyChanged;
}

Clicking the button doesn't do anything :( I tried everything to get this to work, and no dice. Would really appreciate some help!


I tried the following, and still does not work:

  public bool Editable
    {
        get { return (bool)GetValue(EditableProperty); }
        set { SetValue(EditableProperty, value); }
    }

    public static readonly DependencyProperty EditableProperty =
        DependencyProperty.Register("Editable", typeof(bool), typeof(OrderInfoView), new UIPropertyMetadata(false));

解决方案

It looks like your solution may be more complex than necessary. If all you want to do is have a disabled TextBox look like a TextBlock then you can do this using a trigger and a template. Then you can apply that style to all text boxes.

Here's an example of that approach:

<Window x:Class="WpfApplication25.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window1" 
        Height="300" 
        Width="300"
        >

    <Window.Resources>

        <!-- Disable TextBox Style -->
        <Style x:Key="_DisableTextBoxStyle" TargetType="TextBox">
            <Style.Triggers>
                <Trigger Property="IsEnabled" Value="False">
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="TextBox">
                                <!-- 
                                Be sure to apply all necessary TemplateBindings between
                                the TextBox and TextBlock template.
                                -->
                                <TextBlock Text="{TemplateBinding Text}"
                                           FontFamily="{TemplateBinding FontFamily}"
                                           />
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Trigger>
            </Style.Triggers>
        </Style>

    </Window.Resources>

    <StackPanel>
        <TextBox IsEnabled="{Binding IsChecked, ElementName=uiIsEnabled}"
                 Style="{StaticResource _DisableTextBoxStyle}"
                 />

        <ToggleButton x:Name="uiIsEnabled" Content="Enable" IsChecked="True" />
    </StackPanel>
</Window>

这篇关于WPF用户控件绑定问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆