Pergunta

Eu tenho um campo binário no meu banco de dados que é difícil de descrever em uma interface do usuário usando um single "Is XXXX?" - caixa tipo. Eu prefiro usar um par de botões de rádio (por exemplo, "Fazê-lo da maneira Foo" e "Faça do jeito Bar"), mas agora todos os outros campos no meu formulário são ligados a dados para um objeto de negócios. Gostaria de dados-bind o par de botões de rádio para o objeto de negócios, bem como, mas não vêm-se com uma boa maneira de fazê-lo ainda. Posso ligar um dos botões para o campo, de modo que o campo está definido "true" se o botão for selecionado, mas ao selecionar o outro botão faz de-selecionar o primeiro (isto é, os dois botões de rádio estão devidamente emparelhado ), o valor do campo não é atualizado para refletir isso.

Eu gostaria de poder dizer

button1.DataBindings.Add(new Binding("checked", source, "useFoo"));
button2.DataBindings.Add(new Binding("checked", source, "!useFoo"));

mas eu tenho certeza que vai jogar quando ele é executado. Existe uma maneira mais fácil, ou devo apenas colocar mais pensou em como palavra uma única caixa de seleção? Eu não quero adicionar funções extra para lidar com algo tão trivial ...

ETA: Um comentarista sugeriu considerando uma lista suspensa (ComboBox). Eu tinha pensado sobre isso, mas como é que os dados-bind I que a um campo boolean em um banco de dados / Bem em um objeto de negócios? Se eu vincular a SelectedItem à propriedade useFoo, o que iria na coleção de itens? Eu teria que adicionar apenas "True" e "False", ou eu poderia de alguma forma adicionar um objeto par chave / valor que os laços um item exibido ( "Use Foo" / "não usar Foo") para o valor booleano por trás disso? Estou tendo docs constatação de problemas com isso.


Sobre a resposta: a solução que acabou usando envolvidos modificar o objeto de negócios - a idéia básica é muito semelhante ao publicado por Gurge, mas eu vim com ele separadamente antes de ler sua resposta. Em suma, eu adicionei uma propriedade separada que simplesmente retorna !useFoo. Um botão de opção é obrigado a source.UseFoo, eo outro é obrigado a source.UseBar (o nome da nova propriedade). É importante certificar-se a nova propriedade tem ambos os getters e setters, ou você vai acabar com um comportamento muito estranho.

Foi útil?

Solução

Eu encontrei uma maneira de fazer isso usando DataSet / DataTable.

Eu faço uma coluna calculada na DataTable com o IIF(Foo=true, false, true) expressão. Vamos chamada que Bar coluna.

Bar é do tipo booleano. Agora você pode vincular um RadioButton.Checked para Foo e um para Bar.

Para obter verificação Bar / desmarcando a propagar de volta para Foo você deve ir para o código DataTable gerado e adicionar uma linha, o último neste exemplo:

[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public bool Bar {
    get {
        try {
            return ((bool)(this[this.tableradio.BarColumn]));
        }
        catch (global::System.InvalidCastException e) {
            throw new global::System.Data.StrongTypingException("The value for column \'Bar\' in table \'radio\' is DBNull.", e);
        }
    }
    set {
        this[this.tableradio.BarColumn] = value;
        this[this.tableradio.FooColumn] = !value;
    }
}

Outras dicas

  1. Bind o RadioButton que está diretamente ligada ao seu valor booleano (isto é verificada quando o valor é true).
  2. Adicionar um manipulador de eventos para o evento CheckedChanged neste RadioButton que se parece com o seguinte:

    private void radioButton_CheckedChanged(object sender, EventArgs e)
    {
        foreach (Binding b in ((Control)sender).DataBindings)
            b.WriteValue();
    }
    

Se os seus instrumentos de objetos de negócios INotifyPropertyChanged (o que torna mais agradável o trabalho de ligação), você pode adicionar o seguinte código para a interface visual, onde BO é o seu objeto de negócios e é declarado WithEvents e BO.Value é a propriedade booleana que você gostaria de vincular a.

Public Property NotValue() As Boolean
    Get
        Return Not BO.Value
    End Get
    Set(ByVal value As Boolean)
        BO.Value = Not value
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("NotValue"))
    End Set
End Property


Private Sub BO_PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Handles BO.PropertyChanged
    If e.PropertyName = "Value" Then
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("NotValue"))
    End If
End Sub

As seguintes ligações irão conectar os botões de rádio.

RBTrue.DataBindings.Add(New Binding("Checked", Me.BO, "Value", False, DataSourceUpdateMode.OnPropertyChanged))
RBFalse.DataBindings.Add(New Binding("Checked", Me, "NotValue", False, DataSourceUpdateMode.OnPropertyChanged))

A interface visual também deve implementar INotifyPropertyChanged. Este método funciona nos dois sentidos: o valor original é atualizado, se as mudanças na interface e se o valor original muda a interface irá atualizar corretamente

.

me deparei com o mesmo problema, e descobri que é realmente possível com ligação de dados padrão:

button1.DataBindings.Add(new Binding("checked", source, "useFoo", false, DataSourceUpdateMode.OnPropertyChanged);
// no need to databind button 2, since button1.checked 
// is set to false when button2 is checked

Por padrão, DataSourceUpdateMode está definido para OnValidation. Definindo-o como OnPropertyChanged, a mudança é propagada imediatamente para o objeto de ligação de dados.

As minhas implementos objeto de negócios INotifyPropertyChanged;

Ao testar esta solução, eu descobri que meu evento OnPropertyChanged foi demitido duas vezes quando eu estava clicando button2. Para evitar isso, basta definir

button1.CausesValidation = false;
button2.CausesValidation = false;

como mostrado aqui: TextBox licença provoca PropertyChanged demitido duas vezes

fazê-lo manualmente no código. Quando você carregar o formulário definir seus botões de opção de acordo com seu banco de dados. Quando você pressiona um botão "Salvar" loja de estado como desejar. Este exemplo armazena rádios como campos de bits no banco de dados.

        // Load radio state
        radioButton1.Checked = ((myModel)myBindingSource.DataSource).boolOption1;
        radioButton2.Checked = ((myModel)myBindingSource.DataSource).boolOption2;

-

        // Save radio state
        ((myModel)myBindingSource.DataSource).boolOption1 = radioButton1.Checked;
        ((myModel)myBindingSource.DataSource).boolOption2 = radioButton2.Checked;

Eu tentei arrastar itens do painel "Fontes de dados" no Visual Studio 2015, quando eu defini meus botões de rádio como booleans na tabela, mas não há problemas com os booleans não sendo atualizados para false quando outro botão de opção é selecionado. Ao alterar o "CausesValidation" a falsos radiobuttons desmarcada automaticamente quando saltar entre outros campos de entrada de texto.

Você só deve ter de ligar um dos controles enquanto você se certificar que estão no mesmo grupo.

Você também pode considerar uma lista suspensa.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top