none
Carregar combobox sem interferir no datacontext RRS feed

  • Pergunta

  • Olá pessoal,

    me deparei ontem a tarde com o seguinte problema:
    Minha janela tem como DataContext um ViewModel.
    Nesta janela, existe um ComboBox que deve listar os nomes que existem em um determinado arquivo XML. Então eu defino o DataContext deste combo para a propriedade do meu ViewModel que tem um XmlDataProvider (DataContext="{Binding Path=LocalSettingsProvider}")
    O problema, é que eu gostaria de executar um binding twoway da propriedade TEXT do combobox, na propriedade Login da minha ViewModel. Quando tirar o foco da combobox de login, o texto digitado OU selecionado no combo, vai ser o valor da propriedade Login no meu viewmodel.
    Com isso, gerou um erro, pois quando eu defino o DataContext do meu Combo para a propriedade LocalSettingsProvider ele avisa que esta propriedade não tem uma propriedade LOGIN. Ele não está mais mirando no ViewModel.Login e sim no LocalSettingsProvider.Login (que não existe)

    Sei e entendo que isso é certo (defini o datacontext do combobox como outra coisa que é diferente da tela), mas não sei como posso resolver meu problema. Existe como não precisar definir o datacontext do combo (só achei respostas definindo-o)??

    Desde já, grato.
    "Any fool can write code that a computer can understand. Good programmers write code that humans can understand" (Martin Fowler)
    sexta-feira, 22 de janeiro de 2010 11:29

Respostas

  • Neste caso, recomendaria o seguinte: não exponha um provider e sim a coleção de dados do provider. Aí você pega os dados do xml com Linq e expõe uma ObservableCollection, que você pode ligar com o ItemsSource da combo.

    Bruno

    MVP Client Development - http://msmvps.com/blogs/bsonnino
    sábado, 23 de janeiro de 2010 12:20

Todas as Respostas

  • Você não deve definir o DataContext da Combo e sim o ItemsSource

    Bruno
    MVP Client Development - http://msmvps.com/blogs/bsonnino
    sexta-feira, 22 de janeiro de 2010 14:59
  • Bruno, segue meu fonte e não funciona!

    Na ViewModel tem o método que carrega o atributo.
     private void ReadXMLSettingsFile()
            {
                //vou verificar se já existe o caminho do arquivo e o arquivo XML
                if (!this.ExistsXMLSettingsFile(this.m_xmlSettingsPath))
                {//se !NÃO existir o arquivo xml de configuração
                    this.CreateXMLSettingsFile(this.m_xmlSettingsPath);//crio o caminho e o arquivo
                }
    
                this.LocalSettingsProvider = new XmlDataProvider();
                this.LocalSettingsProvider.Source = new Uri(this.m_xmlSettingsPath);
                this.LocalSettingsProvider.XPath = "/configuration/RememberMeList/User";
            }
    e a propriedade que retorna um XMLDataProvider:
            //Cria o atributo privado que guardará o provedor de dados do XML de configuração Local
            private XmlDataProvider m_localSettingsProvider;
            /// <summary>
            /// Retorna o provedor de dados XML do arquivo local de configuração
            /// </summary>
            public XmlDataProvider LocalSettingsProvider
            {
                get { return this.m_localSettingsProvider; }
                private set //set privado. pode ser utilizado apenas nesta classe, para executar o raiseevent
                {
                    this.m_localSettingsProvider = value;//defino o valor
                    base.RaiseEventPropertyChanged("LocalXMLProvider");//disparo o evento
                }
            }
    Ai no XML eu tenho o Window.DataContext, que aponta pro VIEWMODEL:

    <Window x:Class="TwoB.BusinessManager.Client.Views.Access.LoginWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:ViewModelAccess="clr-namespace:TwoB.BusinessManager.Client.ViewModels.Access;assembly=TwoB.BusinessManager.Client.ViewModels"
            Title="2B Business Manager | Login de Acesso"
            Height="480" Width="360"
            MinHeight="480" MinWidth="360">
            
        <Window.Resources>
            <ResourceDictionary>
                <ResourceDictionary.MergedDictionaries>
                    <ResourceDictionary Source="pack://application:,,,/TwoB.BusinessManager.Library.Resources;component/Images/ImageDictionary.xaml" />
                </ResourceDictionary.MergedDictionaries>
            </ResourceDictionary>
        </Window.Resources>
        <Window.DataContext>
            <ViewModelAccess:LoginViewModel x:Name="m_loginViewModel"/>
        </Window.DataContext>
    e lá no combobox do XAML tem:

     <ComboBox Name="cmbLogin" Style="{StaticResource cssLoginDataPanel}" 
                              ItemsSource="{Binding Path=LocalSettingsProvider}" 
                              DisplayMemberPath="Login"
                              IsEditable="True" />
    Dessa forma não funciona. Já tentei mexer em diversas propriedade e nada. Agora, basta colocar esse fonte que funciona perfeitamente:

                    <ComboBox Name="cmbLogin" Style="{StaticResource cssLoginDataPanel}" 
                              ItemsSource="{Binding}" DataContext="{Binding Path=LocalSettingsProvider}" DisplayMemberPath="Login"
                              IsEditable="True" />
    Porém com este código acima (que funciona para popular o combo) não funciona para definir a propriedade TEXT como a propriedade LOGIN do ViewModel, pois o context é diferente.

    O que estou fazendo errado Bruno?
    "Any fool can write code that a computer can understand. Good programmers write code that humans can understand" (Martin Fowler)
    sexta-feira, 22 de janeiro de 2010 15:46
  • Você tentou fazer

    <ComboBox Name="cmbLogin" Style="{StaticResource cssLoginDataPanel}"
                              ItemsSource="{Binding Path=LocalSettingsProvider.Data}"
                              DisplayMemberPath="Login"
                              IsEditable="True" />

    Bruno
    MVP Client Development - http://msmvps.com/blogs/bsonnino
    sexta-feira, 22 de janeiro de 2010 15:57
  • Bruno, tentei e apesar de não gerar erro de binding (no output) a caixa do combobox não foi carregada.
    Mais alguma idéia?
    "Any fool can write code that a computer can understand. Good programmers write code that humans can understand" (Martin Fowler)
    sexta-feira, 22 de janeiro de 2010 16:09
  • Neste caso, recomendaria o seguinte: não exponha um provider e sim a coleção de dados do provider. Aí você pega os dados do xml com Linq e expõe uma ObservableCollection, que você pode ligar com o ItemsSource da combo.

    Bruno

    MVP Client Development - http://msmvps.com/blogs/bsonnino
    sábado, 23 de janeiro de 2010 12:20