Winforms DataBind 到控件的可见属性

发布于 2024-07-16 09:29:10 字数 255 浏览 11 评论 0原文

将数据绑定到控件的可见属性时是否存在任何已知问题?

无论我的属性是什么,该控件始终不可见。

Public ReadOnly Property IsRibbonCategory() As Boolean
    Get
        Return True
    End Get
End Property

我尝试了控件的文本属性和其他属性,它们似乎工作正常。

我正在尝试设置面板的可见属性。

Are there any known issues when databinding to a control's visible property?

The control is always NOT visible regardless of what my property is.

Public ReadOnly Property IsRibbonCategory() As Boolean
    Get
        Return True
    End Get
End Property

I tried the control's text property and other properties and they seem to work correctly.

I am trying to set a Panel's visible property.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

亣腦蒛氧 2024-07-23 09:29:10

我发现,如果您假设与控件的 Visible 属性的绑定已被破坏,那么生活会更好,尽管事实上它有时会起作用。 请参阅 http://support.microsoft.com/kb/327305,其中说了这么多(并且虽然知识库文章适用于 .NET 1.0 和 1.1,但至少在 2.0 中它似乎仍然是一个问题)。

我创建了一个用于创建绑定的实用程序类,除其他外,它为我提供了一个集中的位置来添加解决方法。 它没有实际在 Visible 上创建绑定,而是执行两件事:

  1. 它订阅数据源的 INotifyPropertyChanged.PropertyChanged 事件,并在引发事件时根据需要设置 Visible 值。
  2. 它根据当前数据源值设置Visible的初始值。

这需要一些反射代码,但还不错。 重要的是,您不要绑定 Visible 属性执行解决方法,否则它将无法工作。

I've found that life is better if you assume that binding to a control's Visible property is broken, despite the fact that it sometimes works. See http://support.microsoft.com/kb/327305, which says as much (and while the KB article applies to .NET 1.0 and 1.1, it still seems to be a problem in at least 2.0).

I created a utility class for creating bindings which, among other things, gave me a centralized place to add a work-around. Instead of actually creating a binding on Visible it does two things:

  1. It subscribes to the data source's INotifyPropertyChanged.PropertyChanged event and sets the Visible value as appropriate when the event is raised.
  2. It sets the initial value of Visible according to the current data source value.

This required a little reflection code, but wasn't too bad. It is critical that you don't bind the Visible property and do the work-around or it won't work.

夜清冷一曲。 2024-07-23 09:29:10

解决方法:设置 BindingComplete 事件的 Visible 属性。

我在设置标签的 Visible 属性时遇到了同样的问题 - 始终保持 false,即使设置 Enabled 属性工作正常。

Workaround: Set the Visible property on the BindingComplete event.

I had same issue setting a label's Visible property - always stays false, even though setting the Enabled property works fine.

是伱的 2024-07-23 09:29:10

我刚刚在 .NET 4.7.1 和 Visual Studio 2017 中遇到了这个问题。为了解决这个问题,我将控件上的 Visible 属性更改为最初设置为 True,如下所示我之前将其设置为 False

I just hit this issue in .NET 4.7.1 and Visual Studio 2017. To fix it, I changed the Visible property on my control to be initially set to True, as I had it as False previously.

陈独秀 2024-07-23 09:29:10

要检查的事项:

  • 确保您已实例化具有 IsRibbonCategory 属性的类
  • 您是否将绑定源的属性的数据源设置为该类的实例
  • 数据源更新模式应为“验证时”
  • 确保您没有设置t 在控件上手动将可见属性设置为 false

希望有帮助。 您可以发布更多代码吗?

Things to check:

  • Be sure you've instantiated the class that has the IsRibbonCategory property
  • Did you set the datasource of property of the binding source to the instance of the class
  • The datasource update mode should be on "on validation"
  • Make sure you didn't set the visible property manually to false on the control

Hope that helps. Can you post more code?

歌枕肩 2024-07-23 09:29:10

解决方法是使用组件将数据绑定到控件的可见性属性,而不是直接绑定到控件的可见性属性。
参见下面的代码:

using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

namespace WindowsFormsApplication2
{
  public class ControlVisibilityBinding : Component
  {
    private static readonly object EventControlChanged = new object();
    private static readonly object EventVisibleChanged = new object();

    private System.Windows.Forms.Control _control;
    private bool _visible = true;

    public event EventHandler VisibleChanged
    {
        add { Events.AddHandler(EventVisibleChanged, value); }
        remove { Events.RemoveHandler(EventVisibleChanged, value); }
    }

    public event EventHandler ControlChanged
    {
        add { Events.AddHandler(EventControlChanged, value); }
        remove { Events.RemoveHandler(EventControlChanged, value); }
    }

    public ControlVisibilityBinding()
    {
    }

    public ControlVisibilityBinding(IContainer container)
    {
        container.Add(this);
    }

    [DefaultValue(null)]
    public System.Windows.Forms.Control Control
    {
        get { return _control; }
        set
        {
            if(_control == value)
            {
                return;
            }
            WireControl(_control, false);
            _control = value;
            if(_control != null)
            {
                _control.Visible = _visible;
            }
            WireControl(_control, true);
            OnControlChanged(EventArgs.Empty);
            OnVisibleChanged(EventArgs.Empty);
        }
    }

    [DefaultValue(true)]
    public bool Visible
    {
        get { return _visible; }
        set
        {
            if(_visible != value)
            {
                _visible = value;
            }
            if(Control != null)
            {
                Control.Visible = _visible;
            }
            OnVisibleChanged(EventArgs.Empty);
        }
    }

    private void WireControl(Control control, bool subscribe)
    {
        if(control == null)
        {
            return;
        }
        if(subscribe)
        {
            control.VisibleChanged += Control_VisibleChanged;
        }
        else
        {
            control.VisibleChanged -= Control_VisibleChanged;
        }
    }

    private void Control_VisibleChanged(object sender, EventArgs e)
    {
        OnVisibleChanged(EventArgs.Empty);
    }

    protected virtual void OnVisibleChanged(EventArgs e)
    {
        EventHandler subscribers = (EventHandler)Events[EventVisibleChanged];
        if(subscribers != null)
        {
            subscribers(this, e);
        }
    }

    protected virtual void OnControlChanged(EventArgs e)
    {
        EventHandler subscribers = (EventHandler)Events[EventControlChanged];
        if(subscribers != null)
        {
            subscribers(this, e);
        }
    }
}

static class Program
{
    [STAThread]
    static void Main()
    {
        using(Form form = new Form())
        using(FlowLayoutPanel groupBoxLayoutPanel = new FlowLayoutPanel())
        using(RadioButton visibleButton = new RadioButton())
        using(RadioButton hiddenButton = new RadioButton())
        using(GroupBox groupBox = new GroupBox())
        using(Label text = new Label())
        using(ControlVisibilityBinding visibilityBinding = new ControlVisibilityBinding())
        using(TextBox inputTextBox = new TextBox())
        {
            groupBoxLayoutPanel.Dock = DockStyle.Fill;
            groupBoxLayoutPanel.FlowDirection = FlowDirection.LeftToRight;
            groupBoxLayoutPanel.AutoSize = true;
            groupBoxLayoutPanel.AutoSizeMode = AutoSizeMode.GrowAndShrink;

            visibleButton.Text = "Show Label";
            visibleButton.AutoSize = true;
            hiddenButton.Text = "Hide Label";
            hiddenButton.AutoSize = true;
            groupBoxLayoutPanel.Controls.Add(visibleButton);
            groupBoxLayoutPanel.Controls.Add(hiddenButton);

            inputTextBox.Text = "Enter Label Text Here";
            inputTextBox.Dock = DockStyle.Top;

            groupBox.AutoSize = true;
            groupBox.AutoSizeMode = AutoSizeMode.GrowAndShrink;
            groupBox.Controls.Add(groupBoxLayoutPanel);
            groupBox.Dock = DockStyle.Fill;

            text.AutoSize = true;
            text.ForeColor = Color.Red;
            text.Dock = DockStyle.Bottom;
            text.BorderStyle = BorderStyle.FixedSingle;
            text.Font = new Font(text.Font.FontFamily, text.Font.Size * 1.25f, FontStyle.Bold | FontStyle.Italic);
            text.DataBindings.Add("Text", inputTextBox, "Text", true, DataSourceUpdateMode.Never);

            visibilityBinding.Control = text;
            visibleButton.DataBindings.Add("Checked", visibilityBinding, "Visible", true, DataSourceUpdateMode.OnPropertyChanged);
            Binding binding = hiddenButton.DataBindings.Add("Checked", visibilityBinding, "Visible", true, DataSourceUpdateMode.OnPropertyChanged);
            ConvertEventHandler invertConverter = (sender, e) => e.Value = !((bool)e.Value);
            binding.Format += invertConverter;
            binding.Parse += invertConverter;

            form.Controls.Add(inputTextBox);
            form.Controls.Add(text);
            form.Controls.Add(groupBox);
            Application.Run(form);
        }
    }
}

}

A workaround would be to use a Component to databind to a control's visiblity property instead of directly binding to the control's visibility property.
See below code:

using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

namespace WindowsFormsApplication2
{
  public class ControlVisibilityBinding : Component
  {
    private static readonly object EventControlChanged = new object();
    private static readonly object EventVisibleChanged = new object();

    private System.Windows.Forms.Control _control;
    private bool _visible = true;

    public event EventHandler VisibleChanged
    {
        add { Events.AddHandler(EventVisibleChanged, value); }
        remove { Events.RemoveHandler(EventVisibleChanged, value); }
    }

    public event EventHandler ControlChanged
    {
        add { Events.AddHandler(EventControlChanged, value); }
        remove { Events.RemoveHandler(EventControlChanged, value); }
    }

    public ControlVisibilityBinding()
    {
    }

    public ControlVisibilityBinding(IContainer container)
    {
        container.Add(this);
    }

    [DefaultValue(null)]
    public System.Windows.Forms.Control Control
    {
        get { return _control; }
        set
        {
            if(_control == value)
            {
                return;
            }
            WireControl(_control, false);
            _control = value;
            if(_control != null)
            {
                _control.Visible = _visible;
            }
            WireControl(_control, true);
            OnControlChanged(EventArgs.Empty);
            OnVisibleChanged(EventArgs.Empty);
        }
    }

    [DefaultValue(true)]
    public bool Visible
    {
        get { return _visible; }
        set
        {
            if(_visible != value)
            {
                _visible = value;
            }
            if(Control != null)
            {
                Control.Visible = _visible;
            }
            OnVisibleChanged(EventArgs.Empty);
        }
    }

    private void WireControl(Control control, bool subscribe)
    {
        if(control == null)
        {
            return;
        }
        if(subscribe)
        {
            control.VisibleChanged += Control_VisibleChanged;
        }
        else
        {
            control.VisibleChanged -= Control_VisibleChanged;
        }
    }

    private void Control_VisibleChanged(object sender, EventArgs e)
    {
        OnVisibleChanged(EventArgs.Empty);
    }

    protected virtual void OnVisibleChanged(EventArgs e)
    {
        EventHandler subscribers = (EventHandler)Events[EventVisibleChanged];
        if(subscribers != null)
        {
            subscribers(this, e);
        }
    }

    protected virtual void OnControlChanged(EventArgs e)
    {
        EventHandler subscribers = (EventHandler)Events[EventControlChanged];
        if(subscribers != null)
        {
            subscribers(this, e);
        }
    }
}

static class Program
{
    [STAThread]
    static void Main()
    {
        using(Form form = new Form())
        using(FlowLayoutPanel groupBoxLayoutPanel = new FlowLayoutPanel())
        using(RadioButton visibleButton = new RadioButton())
        using(RadioButton hiddenButton = new RadioButton())
        using(GroupBox groupBox = new GroupBox())
        using(Label text = new Label())
        using(ControlVisibilityBinding visibilityBinding = new ControlVisibilityBinding())
        using(TextBox inputTextBox = new TextBox())
        {
            groupBoxLayoutPanel.Dock = DockStyle.Fill;
            groupBoxLayoutPanel.FlowDirection = FlowDirection.LeftToRight;
            groupBoxLayoutPanel.AutoSize = true;
            groupBoxLayoutPanel.AutoSizeMode = AutoSizeMode.GrowAndShrink;

            visibleButton.Text = "Show Label";
            visibleButton.AutoSize = true;
            hiddenButton.Text = "Hide Label";
            hiddenButton.AutoSize = true;
            groupBoxLayoutPanel.Controls.Add(visibleButton);
            groupBoxLayoutPanel.Controls.Add(hiddenButton);

            inputTextBox.Text = "Enter Label Text Here";
            inputTextBox.Dock = DockStyle.Top;

            groupBox.AutoSize = true;
            groupBox.AutoSizeMode = AutoSizeMode.GrowAndShrink;
            groupBox.Controls.Add(groupBoxLayoutPanel);
            groupBox.Dock = DockStyle.Fill;

            text.AutoSize = true;
            text.ForeColor = Color.Red;
            text.Dock = DockStyle.Bottom;
            text.BorderStyle = BorderStyle.FixedSingle;
            text.Font = new Font(text.Font.FontFamily, text.Font.Size * 1.25f, FontStyle.Bold | FontStyle.Italic);
            text.DataBindings.Add("Text", inputTextBox, "Text", true, DataSourceUpdateMode.Never);

            visibilityBinding.Control = text;
            visibleButton.DataBindings.Add("Checked", visibilityBinding, "Visible", true, DataSourceUpdateMode.OnPropertyChanged);
            Binding binding = hiddenButton.DataBindings.Add("Checked", visibilityBinding, "Visible", true, DataSourceUpdateMode.OnPropertyChanged);
            ConvertEventHandler invertConverter = (sender, e) => e.Value = !((bool)e.Value);
            binding.Format += invertConverter;
            binding.Parse += invertConverter;

            form.Controls.Add(inputTextBox);
            form.Controls.Add(text);
            form.Controls.Add(groupBox);
            Application.Run(form);
        }
    }
}

}

蒲公英的约定 2024-07-23 09:29:10

这是我的转身,这可能很愚蠢,但它成功了很多次。

我在表单中放置了一个 Panel 控件,使其填充我的表单,然后将所有内容都放入该面板中。 我绑定 Visible 属性的所有控件都会看到其可见性根据 DataGridView 中的对象而变化。

表单结构

Here is my turn around, it may be stupid but it worked many times.

I put one Panel control in my form, I make it to Fill my form and I put everything in that Panel. All the controls I bind the Visible property see their visibility change according to the objects in my DataGridView.

Form structure

指尖微凉心微凉 2024-07-23 09:29:10

尝试在表单加载中手动绑定。

发现在表单设计器中绑定到 BindingSource 对象中的属性不起作用。 必须在代码隐藏(表单的加载事件)中设置绑定。

可能是因为在 BindingSource 使用 true 或 false 值完全初始化之前,绑定到 Visible 的属性暂时被设置为 False,因为按钮/面板/控件正在初始化,表单正在加载。

这是一个对我有用的手动绑定示例:

private void Form_Load(object sender, EventArgs e)
{    
    button1.DataBindings.Add("Visible", someBindingSource, "SomePropertyOfObject", true, DataSourceUpdateMode.OnValidation);
}

Try manual binding in Form Load.

Found that binding to a property in a BindingSource object in the form designer didn't work. Had to set the binding in code-behind (Form's Load event) instead.

Probably due the property bound to Visible was being set to False momentarily, as the Button/Panel/control was being initialized, as the Form was loading, before the BindingSource was fully initialized with either a true or false value.

Here is a manual binding example that worked for me:

private void Form_Load(object sender, EventArgs e)
{    
    button1.DataBindings.Add("Visible", someBindingSource, "SomePropertyOfObject", true, DataSourceUpdateMode.OnValidation);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文