Pergunta

Então, eu estou aprendendo WPF agora, e quero fazer um databind simples entre um valor booleano, e se ou não um MenuItem está habilitado ou não.

Eu tenho codificado assim:

<MenuItem Name="miSaveFile" Header="Save" Click="miSaveFile_Click"
IsEnabled="{Binding}" />

E no arquivo .cs I definido:

miSaveFile.DataContext = dataChanged;

Por alguma razão o MenuItem não parece estar refletindo corretamente o estado de DataChanged.

O que eu estou ausente?

Foi útil?

Solução

Você é melhor fora de ligação a um objeto do que para um tipo primitivo. Este objeto é muitas vezes referido como o "modelo" para a sua exibição.

WPF usa a interface INotifyPropertyChanged para o modelo (ou muitas vezes vêem-modelo) para notificar a visão de que o modelo mudou estados.

Então, primeiro você deseja definir uma classe de dados como o modelo que implementa a interface INotifyPropertyChanged e dispara o evento PropertyChanged sempre que uma propriedade é alterada.

Quando você define uma ligação, você tem 5 principais elementos sobre a ligação que se preocupar. A ligação tem um objeto de origem, um caminho de origem no objeto de origem, um objeto de destino, uma propriedade de destino no objeto de destino, e um conversor opcional.

Se você não especificar a fonte, o padrão é o DataContext do controle da ligação é definida no. Há outras opções para definir a fonte. Aqui é um artigo da Microsoft sobre como configurar a fonte. Você pode, então, definir o caminho de uma propriedade para retirar da fonte para a ligação. No seu caso, a fonte é um boolean e não há nenhum caminho, porque a ligação está usando todo o objeto de origem.

O alvo é sempre o controle que você definir a ligação, e a propriedade de destino é a propriedade sobre esse controle que você está ligado. Neste caso, MenuItem e IsEnabled.

Um conversor pode, opcionalmente, converter o valor de origem para um valor que é compatível com a propriedade de destino. Você pode usar qualquer objeto para um conversor que implementa IValueConverter ou IMultiValueConverter (para MutliBindings).

No seu caso, gostaria de primeiro criar um modelo que implementa INotifyPropertyChanged. Em seguida, eu iria atribuir os DataContext do menu para uma instância do modelo. Então eu iria definir a ligação a:

IsEnabled="{Binding Path=EnableFlag}"

(Onde EnableFlag é uma propriedade booleana no modelo que pretende menu para se ligam a)

Se você configurar a interface INotifyPropertyChanged corretamente, o item de menu será ativado / desativado sempre que você alterar esta propriedade no modelo.

Outras dicas

Para um MenuItem, não seria uma melhor abordagem para usar o modelo de comando, em vez de Click e propriedades IsEnabled?

Depois de InitialiseComponent ():

this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Save, fileSaveExecuted, fileSaveCanExecute));

Os métodos adicionais:

/* here is where you set e.CanExecute true for enabled: */
    private void fileSaveCanExecute(object x, CanExecuteRoutedCommandEventArgs e)) { e.CanExecute = ...; e.Handled = true; }
/* here is where you act on the command: */
    private void fileSaveExecuted(object sender, ExecutedRoutedEventArgs e) { ... }

XAML:

<MenuItem Header="_Save" Command="Save"/>

Como é que o know UI quando a variável DataChanged mudou realmente?

Eu normalmente ligam-se a uma propriedade em um objeto, e deixar que a classe implementar INotifyPropertyChanged. A interface do usuário é, então, "automagicamente" atualizado sempre que o evento PropertyChanged é invocado.

Então, eu teria

<MenuItem Name="miSaveFile" Header="Save" Click="miSaveFile_Click"
IsEnabled="{Binding DataChanged}"</MenuItem>

e defina miSaveFile.DataContext = myObject.DataChanged (MyObject pode ser isso, se você estiver usando o codebehind)

Edit: Eu só fiz um teste rápido. Se você definir o contexto de dados diretamente para a propriedade DataChanged, não é adicionada uma assinatura para o evento PropertyChanged no objeto proprietário. Mas a solução sugiro obras.

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