none
Actulizar el contexto de datos después de guardar RRS feed

  • Pregunta

  • Hola, el siguiente código es el view model de una lista de Categorías de productos, está enlazado a datos mediante EF6. Al ejecutar el comando "SaveCommand" se guarda bien, pero si he insertado una nueva categoría en el DataGrid me sigue apreciendo con el ID por defecto (0). ¿Cuál sería la forma de que al guardar se reflejase el cambio en "Category ID". Gracias

    Código del ViewModel

     class MW2ViewModel:INotifyPropertyChanged
        {  
            public event PropertyChangedEventHandler PropertyChanged;   
            private ProductContext _context = new ProductContext();
            private ICommand _saveCommand;
            public ICommand SaveCommand
            {
                get { return _saveCommand; }
            }
            public MW2ViewModel()
            {
                 _context.Categories.ToList();
                Categorias=_context.Categories.Local;

                _saveCommand = new RelayCommand(
                o => { _context.SaveChanges(); NotifyPropertyChanged("Categorias"); },
                o => _context.ChangeTracker.HasChanges());           
            }
              private ObservableCollection<Categories> _categorias;
              public ObservableCollection<Categories> Categorias
              {
                  get
                  {
                      return _categorias;
                  }
                  set
                  {
                      _categorias = value;
                      NotifyPropertyChanged();
                  }
              }
              private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
              {
                  if (PropertyChanged != null)
                  {
                      PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                  }
              }

    XAML de la ventana

    <Window
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:WPFwithEFSample" x:Class="WPFwithEFSample.MW2"
            Title="MW2" Height="300" Width="300">
        <Window.DataContext>
            <local:MW2ViewModel/>
        </Window.DataContext>
        <Grid>
            <DataGrid x:Name="categoriesDataGrid" RowDetailsVisibilityMode="VisibleWhenSelected" Margin="52,10,31,142" ItemsSource="{Binding Categorias}" EnableRowVirtualization="True" AutoGenerateColumns="False" CanUserDeleteRows="False" CanUserAddRows="True" >
                <DataGrid.Columns>
                    <DataGridTextColumn x:Name="categoryIdColumn" Width="SizeToHeader" Header="Category Id" Binding="{Binding CategoryId}" IsReadOnly="True"/>
                    <DataGridTextColumn x:Name="nameColumn" Width="SizeToHeader" Header="Name" Binding="{Binding Name}"/>
                </DataGrid.Columns>
            </DataGrid>
            <Button Content="Button" HorizontalAlignment="Left" Margin="108,150,0,0" VerticalAlignment="Top" Width="75" Command="{Binding SaveCommand}"/>

        </Grid>
    </Window>


    Juan Pablo Toledo España


    • Editado jpabloace jueves, 19 de febrero de 2015 9:08
    jueves, 19 de febrero de 2015 7:08

Respuestas

  • donde defines la variable _categorias ? porqe en el codigo que habias puesto no esta declarada

    para que refleje el cambio debe ser una nueva instancia, por eso quiezas haya que usar

    _saveCommand = new RelayCommand(
                o => {
    
                      _context.SaveChanges();
    
                     var categorias = _context.Categories.ToList();
                     this.Categorias= new ObservableCollection<Categories>(categorias);
    
                     NotifyPropertyChanged("Categorias");
    
                    },
                o => _context.ChangeTracker.HasChanges()); 

    sino es una nueva instancia el grid no reconoce los cambios

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    • Marcado como respuesta jpabloace sábado, 21 de febrero de 2015 12:34
    sábado, 21 de febrero de 2015 12:22
  • Al final, con las "Controles de comportamiento" de "Blend" conseguí actualizar desde xaml.

    <Window.Triggers>
    		<EventTrigger RoutedEvent="ButtonBase.Click" SourceName="button"/>
    </Window.Triggers>

    <Button x:Name="button" Content="Button" HorizontalAlignment="Left" Margin="108,150,0,0" VerticalAlignment="Top" Width="75" Command="{Binding SaveCommand}"> <i:Interaction.Triggers> <i:EventTrigger EventName="Click"> <ei:CallMethodAction TargetObject="{Binding Items, ElementName=categoriesDataGrid}" MethodName="Refresh"/> </i:EventTrigger> </i:Interaction.Triggers> </Button>



    Juan Pablo Toledo España



    • Marcado como respuesta jpabloace sábado, 21 de febrero de 2015 10:32
    • Editado jpabloace domingo, 22 de febrero de 2015 8:54
    sábado, 21 de febrero de 2015 10:32

Todas las respuestas

  • hola

    por lo que planteas el problema no arece ser de EF, sino mas bien de WPF, ya que al grabar la informacion el grid no refleja las actualizaciones

    entiendo que deberia realizar un NotifyPropertyChanged pero de la propiedad CategoryId para que esta se actualice

    o sno recomendaria que la categoria la agregues con controles fuera del grid, defines un textbox para la descripcion y un label para el id

    en un boton define el SaveCommand y que en esta operacion grabes la entidad en EF y ademas la agregas en la coleccion de entidades asignada al grid, de esta forma el propertychange si notara el cambio y actualizara

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    jueves, 19 de febrero de 2015 10:47
  • tambien podrias ver de definir el Mode en el ItemsSource para que sea TwoWay

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    jueves, 19 de febrero de 2015 10:50
  • Hola, gracias, ambas cosas las he probado, pero sigue sin actualizarse el datagrid. ¿Como podría recargar el contexto nuevamente desde la base de datos? por si es ese el problema. Gracias

    Juan Pablo Toledo España

    jueves, 19 de febrero de 2015 12:11
  • Hola. He puesto esto en el evento en evento Click="Button_Click" 

    "this.categoriesDataGrid.Items.Refresh();"

    y se actualiza, por lo que no es problema del EF.

    Pero me gustaría no tenerlo en en code behind de la vista, ¿Cómo puedo hacer que el botón actualice el Datagrid al ser pulsado? ¿Con un trigger? pero no se como.

    Gracias


    Juan Pablo Toledo España

    jueves, 19 de febrero de 2015 18:02
  • hola

    que pasa si usas

     _saveCommand = new RelayCommand(
                o => {
    
                      _context.SaveChanges();
    
                     var categorias = _context.Categories.ToList();
                     this.Categorias= categorias;
    
                     NotifyPropertyChanged("Categorias");
    
                    },
                o => _context.ChangeTracker.HasChanges()); 

    o sea vuelves a cargar la lista de categorias

    saludos

             

    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    jueves, 19 de febrero de 2015 20:58
  • Hola. Gracias. Salvando un problema de tipos entre List y ObservableCollection, no cambia nada en la vista. Al poner lo que comenté en una respuesta anterior "this.categoriesDataGrid.Items.Refresh();" en el evento del botón (además de asociarle el comando) si actualiza el Grid, pero quiero dejar el code behind limpio. A lo mejor con trigger en el xaml, pero he hecho varias pruebas sin éxito.

    Gracias


    Juan Pablo Toledo España

    jueves, 19 de febrero de 2015 22:20
  • Al final, con las "Controles de comportamiento" de "Blend" conseguí actualizar desde xaml.

    <Window.Triggers>
    		<EventTrigger RoutedEvent="ButtonBase.Click" SourceName="button"/>
    </Window.Triggers>

    <Button x:Name="button" Content="Button" HorizontalAlignment="Left" Margin="108,150,0,0" VerticalAlignment="Top" Width="75" Command="{Binding SaveCommand}"> <i:Interaction.Triggers> <i:EventTrigger EventName="Click"> <ei:CallMethodAction TargetObject="{Binding Items, ElementName=categoriesDataGrid}" MethodName="Refresh"/> </i:EventTrigger> </i:Interaction.Triggers> </Button>



    Juan Pablo Toledo España



    • Marcado como respuesta jpabloace sábado, 21 de febrero de 2015 10:32
    • Editado jpabloace domingo, 22 de febrero de 2015 8:54
    sábado, 21 de febrero de 2015 10:32
  • donde defines la variable _categorias ? porqe en el codigo que habias puesto no esta declarada

    para que refleje el cambio debe ser una nueva instancia, por eso quiezas haya que usar

    _saveCommand = new RelayCommand(
                o => {
    
                      _context.SaveChanges();
    
                     var categorias = _context.Categories.ToList();
                     this.Categorias= new ObservableCollection<Categories>(categorias);
    
                     NotifyPropertyChanged("Categorias");
    
                    },
                o => _context.ChangeTracker.HasChanges()); 

    sino es una nueva instancia el grid no reconoce los cambios

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    • Marcado como respuesta jpabloace sábado, 21 de febrero de 2015 12:34
    sábado, 21 de febrero de 2015 12:22
  • Hola. Gracias. Tienes razón. Así si funciona.

    Juan Pablo Toledo España

    sábado, 21 de febrero de 2015 12:37
  • Hola. Gracias. Ahora me funciona, pero me da un error (que sale desde el principio, pero compilaba y la aplicación se ejecutaba por lo que no me he preocupado de él hasta ahora) de que "No se encuentra ninguna cadena de conexión denominada 'ProductContext' en el archivo de configuración de la aplicación.


    Y este es el contenido de App.config en el que si está declarado el ProductContext

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      <configSections>
        <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
        <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
      </configSections>
      <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
      </startup>
      <entityFramework>
        <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
        <providers>
          <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
        </providers>
      </entityFramework>
      <connectionStrings>
        <add name="ProductContext" connectionString="metadata=res://*/ProductModel.csdl|res://*/ProductModel.ssdl|res://*/ProductModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=jp-toshiba\sqlexpress;initial catalog=Productos;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />
      </connectionStrings>
    </configuration>


    Juan Pablo Toledo España



    • Editado jpabloace sábado, 21 de febrero de 2015 22:41
    sábado, 21 de febrero de 2015 22:40