quinta-feira, 18 de outubro de 2012
Entity Framework Json Serializer
Available at codeplex, a helper class to serialize EntityFramework entities with Asp.NET MVC JsonResult. This helper class solve the "Circular Reference" problem.
For more information: EFJson.
Entity Framework Json Serializer
Está disponível para download uma classe para serializar classes do EntityFramework em conjunto com o JsonResult do Asp.NET MVC. Esta classe evita o erro de referência circular.
Para mais detalhes: EFJson.
Para mais detalhes: EFJson.
sexta-feira, 10 de fevereiro de 2012
Problema IE, IFRAME e PDF
Ontem tive um problema completamente inesperado.
Eu estava tentando mostrar um PDF dentro de um <iframe>. Este era meu código:
<iframe src="algumdoc.pdf" width="100%" height="100%"><iframe>
Como tudo na WEB testei no FireFox e depois no Chrome, funcionou perfeitamente. Quando fui testar no IE, ele simplesmente travou e tive que fechá-lo.
Testei na máquina de mais algumas pessoas o mesmo acontecia.
Culpa do IE? Culpa da Adobe? Não sei, mas precisava resolver o problema.
Após algumas pesquisas achei uma outra maneira de mostrar um arquivo PDF:
<embed src="algumdoc.pdf" width="100%" height="100%"></embed>
A solução é muito simples, porém levei algumas horas para achá-la.
Eu estava tentando mostrar um PDF dentro de um <iframe>. Este era meu código:
<iframe src="algumdoc.pdf" width="100%" height="100%"><iframe>
Como tudo na WEB testei no FireFox e depois no Chrome, funcionou perfeitamente. Quando fui testar no IE, ele simplesmente travou e tive que fechá-lo.
Testei na máquina de mais algumas pessoas o mesmo acontecia.
Culpa do IE? Culpa da Adobe? Não sei, mas precisava resolver o problema.
Após algumas pesquisas achei uma outra maneira de mostrar um arquivo PDF:
<embed src="algumdoc.pdf" width="100%" height="100%"></embed>
A solução é muito simples, porém levei algumas horas para achá-la.
sábado, 1 de outubro de 2011
Teched 2011
Fui ao teched este ano e estou aqui para contar o que achei do evento.
O evento é bem organizado em questão de infraestrutura, mas achei alguns pontos negativos o que desanima muito.
O primeiro motivo é a questão das coisas nos EUA ocorrerem antes . Com isso, se você é uma pessoa que costuma estudar bastante você não encontrará nada de novo nas apresentações, e até mesmo nada que complemente o que você ja sabe.
O segundo motivo são as pessoas escolhidas para apresentar a tecnologia, apesar de serem MVP etc, isso não significa que são didáticos, por isso, de mais de dez palestras que eu fui, apenas duas foram bem apresentadas, com uma certa didática. Vale a pena elogiar os palestrantes dessas duas palestras que foram Giovani Bassi, Guadalupe Casuso e Lalo Steinmann.
A minha opinião vem das palestras de desenvolvimento, mas ouvi muitas pessoas pela parte de infra reclamando também pela má qualidade das palestras.
Não quero fazer desta postagem uma crítica, mas apenas um aviso para as pessoas que pretendem ir aos próximos e possuem o perfil citado acima não se desaponte, afinal o preço da inscrição não é nada barato, e com toda sinceridade, o evento não vale o que se paga.
O evento é bem organizado em questão de infraestrutura, mas achei alguns pontos negativos o que desanima muito.
O primeiro motivo é a questão das coisas nos EUA ocorrerem antes . Com isso, se você é uma pessoa que costuma estudar bastante você não encontrará nada de novo nas apresentações, e até mesmo nada que complemente o que você ja sabe.
O segundo motivo são as pessoas escolhidas para apresentar a tecnologia, apesar de serem MVP etc, isso não significa que são didáticos, por isso, de mais de dez palestras que eu fui, apenas duas foram bem apresentadas, com uma certa didática. Vale a pena elogiar os palestrantes dessas duas palestras que foram Giovani Bassi, Guadalupe Casuso e Lalo Steinmann.
A minha opinião vem das palestras de desenvolvimento, mas ouvi muitas pessoas pela parte de infra reclamando também pela má qualidade das palestras.
Não quero fazer desta postagem uma crítica, mas apenas um aviso para as pessoas que pretendem ir aos próximos e possuem o perfil citado acima não se desaponte, afinal o preço da inscrição não é nada barato, e com toda sinceridade, o evento não vale o que se paga.
terça-feira, 7 de junho de 2011
Entity Framework NavigationProperties e a Interface INotifyPropertyChanging
O WPF assim como o Silverlight usam o evento PropertyChanging da interface INotifyPropertyChanging para atualizar os bindings dos controles.
As entidades do EntityFramework ja tratam isso pra você, por isso você não tem que se preocupar, veja um exemplo:
[EdmScalarPropertyAttribute(EntityKeyProperty=false, IsNullable=true)]
[DataMemberAttribute()]
public string Nome
{
get
{
return _Nome;
}
set
{
OnNomeChanging(value);
ReportPropertyChanging("Nome");
_Nome= StructuralObject.SetValidValue(value);
ReportPropertyChanged("Nome");
OnNomeChanged();
}
}
Porém, quando se há um relacionamento como, por exemplo, uma pessoa possui várias compras, e você está trabalhando com a entidade Compra, se você fizer:
compra.Pessoa = pessoa;
e caso o seu TextBox esteja com o binding para o Nome da Pessoa relacionado:
<TextBox Text="{Binding Pessoa.Nome}" />
o texto do TextBox não será atualizado porque não há eventos que notifique essa mudança, veja como é implementado o get e o set de Pessoa:
[XmlIgnoreAttribute()]
[SoapIgnoreAttribute()]
[DataMemberAttribute()]
[EdmRelationshipNavigationPropertyAttribute("Model", "FK__Pessoa_Compra", "Pessoa")]
public Pessoa Pessoa
{
get
{
return ((IEntityWithRelationships)this).RelationshipManager.GetRelatedReference<Pessoa>("Model.FK__Pessoa_Compra", "Pessoa").Value;
}
set
{
((IEntityWithRelationships)this).RelationshipManager.GetRelatedReference<Pessoa> ("Model.FK__Pessoa_Compra", "Pessoa").Value = value;
}
}
Por sorte, o EntityFramework possui eventos que você pode utilizar para reverter esta situação.
Para toda referência há uma ou mais propriedades que se relacionam entre as tabelas, e com isso elas também existem nas entidades do EntityFramework. No meu caso há uma coluna chamada IdPessoa do tipo int na entidade Compra. Essas colunas são atualizadas assim que você atribui a nova pessoa na referência, desta maneira se a pessoa tiver o Id = 15, o compra.IdPessoa também será 15 quando eu fizer:
compra.Pessoa = pessoa, e todos os eventos PropertyChanging e PropertyChanged serão disparados.
Dessa maneira podemos usar o evento parcial dessa coluna para notificar nossa interface da mudança dos valores:
public partial class Compra
{
partial void OnIdPessoaChanged()
{
OnPropertyChanged("Pessoa");
}
partial void OnIdPessoaChanging(int value)
{
OnPropertyChanging("Pessoa");
}
}
Repare que a string passada como parâmetro é Pessoa que é o nome da nossa propriedade de relacionamento.
Note também que esta classe deve estar no mesmo namespace da classe gerada pelo EntityFramework.
Até a próxima.
As entidades do EntityFramework ja tratam isso pra você, por isso você não tem que se preocupar, veja um exemplo:
[EdmScalarPropertyAttribute(EntityKeyProperty=false, IsNullable=true)]
[DataMemberAttribute()]
public string Nome
{
get
{
return _Nome;
}
set
{
OnNomeChanging(value);
ReportPropertyChanging("Nome");
_Nome= StructuralObject.SetValidValue(value);
ReportPropertyChanged("Nome");
OnNomeChanged();
}
}
Porém, quando se há um relacionamento como, por exemplo, uma pessoa possui várias compras, e você está trabalhando com a entidade Compra, se você fizer:
compra.Pessoa = pessoa;
e caso o seu TextBox esteja com o binding para o Nome da Pessoa relacionado:
<TextBox Text="{Binding Pessoa.Nome}" />
o texto do TextBox não será atualizado porque não há eventos que notifique essa mudança, veja como é implementado o get e o set de Pessoa:
[XmlIgnoreAttribute()]
[SoapIgnoreAttribute()]
[DataMemberAttribute()]
[EdmRelationshipNavigationPropertyAttribute("Model", "FK__Pessoa_Compra", "Pessoa")]
public Pessoa Pessoa
{
get
{
return ((IEntityWithRelationships)this).RelationshipManager.GetRelatedReference<Pessoa>("Model.FK__Pessoa_Compra", "Pessoa").Value;
}
set
{
((IEntityWithRelationships)this).RelationshipManager.GetRelatedReference<Pessoa> ("Model.FK__Pessoa_Compra", "Pessoa").Value = value;
}
}
Por sorte, o EntityFramework possui eventos que você pode utilizar para reverter esta situação.
Para toda referência há uma ou mais propriedades que se relacionam entre as tabelas, e com isso elas também existem nas entidades do EntityFramework. No meu caso há uma coluna chamada IdPessoa do tipo int na entidade Compra. Essas colunas são atualizadas assim que você atribui a nova pessoa na referência, desta maneira se a pessoa tiver o Id = 15, o compra.IdPessoa também será 15 quando eu fizer:
compra.Pessoa = pessoa, e todos os eventos PropertyChanging e PropertyChanged serão disparados.
Dessa maneira podemos usar o evento parcial dessa coluna para notificar nossa interface da mudança dos valores:
public partial class Compra
{
partial void OnIdPessoaChanged()
{
OnPropertyChanged("Pessoa");
}
partial void OnIdPessoaChanging(int value)
{
OnPropertyChanging("Pessoa");
}
}
Repare que a string passada como parâmetro é Pessoa que é o nome da nossa propriedade de relacionamento.
Note também que esta classe deve estar no mesmo namespace da classe gerada pelo EntityFramework.
Até a próxima.
quinta-feira, 2 de junho de 2011
WPF Calendar com BoldedDates
O controle Calendar do WPF é muito parecido com o MonthCalendar do WindowsForms. Porém como muito se acontece no WPF você tem que abrir a cabeça quando quer adicionar uma funcionalidade mesmo que ela fosse muito fácil no WindowsForms. Isso se deve ao fato do WPF possui seus controles muito mais poderosos, porém poder não quer dizer mais simples de ser utilizado.
Para fazer a mesma funcionalidade do BoldedDates do MonthCalendar você tem que trabalhar com CalendarDayButtonStyle em conjunto com o IValueConverter.
Caso você ja saiba as datas que devem ficar bold, você pode fazer da seguinte maneira:
1) Declare seu convert:
namespace WPFBoldDates
{
public class BoldDateConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if(System.Convert.ToDateTime(value) == new DateTime(2011, 06, 06))
{
return FontWeights.Bold;
}
return FontWeights.Normal;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return value;
}
}
}
2) Configura o style:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:my="clr-namespace:WPFBoldDates"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<my:BoldDateConverter x:Key="boldConverter" />
</Window.Resources>
<Grid>
<Calendar x:Name="calendario">
<Calendar.CalendarDayButtonStyle>
<Style TargetType="CalendarDayButton">
<Setter Property="FontWeight" Value="{Binding Converter={StaticResource boldConverter}}" />
</Style>
</Calendar.CalendarDayButtonStyle>
</Calendar>
</Grid>
</Window>
Pronto, o dia 06/06/2011 ficará em negrito.
Caso queira trabalhar com datas dinâmicas você pode utilizar um CollectionViewSource.
1) Adicione um recurso para seu Window do tipo CollectionViewSource e passe ela como parâmetro do seu binding:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:my="clr-namespace:WPFBoldDates"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<my:BoldDateConverter x:Key="boldConverter" />
<CollectionViewSource x:Key="dates" />
</Window.Resources>
<Grid>
<Calendar x:Name="calendario">
<Calendar.CalendarDayButtonStyle>
<Style TargetType="CalendarDayButton">
<Setter Property="FontWeight" Value="{Binding Converter={StaticResource boldConverter}, ConverterParameter={StaticResource dates}}" />
</Style>
</Calendar.CalendarDayButtonStyle>
</Calendar>
</Grid>
</Window>
2) No construtor do seu Window inicialize o CollectionViewSource:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
List<DateTime> dates = new List<DateTime>();
// Só para demonstração, você pode optar por ir no banco de dados
dates.Add(new DateTime(2011, 6, 6));
CollectionViewSource source = FindResource("dates") as CollectionViewSource;
source.Source = dates;
}
}
3) Para finalizar ajuste seu IValueConverter:
public class BoldDateConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
List<DateTime> dates = (parameter as CollectionViewSource).Source as List<DateTime>;
if(dates.Contains(System.Convert.ToDateTime(value)))
return FontWeights.Bold;
return FontWeights.Normal;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return value;
}
}
}
Como você pode ver, um tanto grande nosso esforço, porém não se limite apenas a usar o bold. Com style vocde formatar seu botão completamente para que ele atenda suas necessidades.
Até a próxima.
Para fazer a mesma funcionalidade do BoldedDates do MonthCalendar você tem que trabalhar com CalendarDayButtonStyle em conjunto com o IValueConverter.
Caso você ja saiba as datas que devem ficar bold, você pode fazer da seguinte maneira:
1) Declare seu convert:
namespace WPFBoldDates
{
public class BoldDateConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if(System.Convert.ToDateTime(value) == new DateTime(2011, 06, 06))
{
return FontWeights.Bold;
}
return FontWeights.Normal;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return value;
}
}
}
2) Configura o style:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:my="clr-namespace:WPFBoldDates"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<my:BoldDateConverter x:Key="boldConverter" />
</Window.Resources>
<Grid>
<Calendar x:Name="calendario">
<Calendar.CalendarDayButtonStyle>
<Style TargetType="CalendarDayButton">
<Setter Property="FontWeight" Value="{Binding Converter={StaticResource boldConverter}}" />
</Style>
</Calendar.CalendarDayButtonStyle>
</Calendar>
</Grid>
</Window>
Pronto, o dia 06/06/2011 ficará em negrito.
Caso queira trabalhar com datas dinâmicas você pode utilizar um CollectionViewSource.
1) Adicione um recurso para seu Window do tipo CollectionViewSource e passe ela como parâmetro do seu binding:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:my="clr-namespace:WPFBoldDates"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<my:BoldDateConverter x:Key="boldConverter" />
<CollectionViewSource x:Key="dates" />
</Window.Resources>
<Grid>
<Calendar x:Name="calendario">
<Calendar.CalendarDayButtonStyle>
<Style TargetType="CalendarDayButton">
<Setter Property="FontWeight" Value="{Binding Converter={StaticResource boldConverter}, ConverterParameter={StaticResource dates}}" />
</Style>
</Calendar.CalendarDayButtonStyle>
</Calendar>
</Grid>
</Window>
2) No construtor do seu Window inicialize o CollectionViewSource:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
List<DateTime> dates = new List<DateTime>();
// Só para demonstração, você pode optar por ir no banco de dados
dates.Add(new DateTime(2011, 6, 6));
CollectionViewSource source = FindResource("dates") as CollectionViewSource;
source.Source = dates;
}
}
3) Para finalizar ajuste seu IValueConverter:
public class BoldDateConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
List<DateTime> dates = (parameter as CollectionViewSource).Source as List<DateTime>;
if(dates.Contains(System.Convert.ToDateTime(value)))
return FontWeights.Bold;
return FontWeights.Normal;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return value;
}
}
}
Como você pode ver, um tanto grande nosso esforço, porém não se limite apenas a usar o bold. Com style vocde formatar seu botão completamente para que ele atenda suas necessidades.
Até a próxima.
quarta-feira, 1 de junho de 2011
WPF DataGrid e DocumentViewer
Acabo de passar por mais um problema que gostaria de compartilhar com vocês.
Desta vez o problema foi tentar mostrar no DocumentViewer um DataGrid com paginação e tudo.
Como é de se esperar não estou aqui hoje para explicar passo a passo o código, estou aqui para dar uma solução para as pessoas que possuem o mesmo problema.
Criei uma classe chamada PrintExtensions.
Dentro dela há duas funções, uma para fazer uma cópia do DataGrid e outra para mostrar no DocumentViewer qualquer FrameworkElement, esta segunda função eu retirei do Blog do Telerik.
O arquivo com o código encontra-se aqui.
Para usar a função apenas faça:
DocumentViewer document = new DocumentViewer();
document.Document = PrintExtensions.PrintDataGrid(dataGrid1, new PrintDialog());
Espero ter ajudado e até a próxima.
Desta vez o problema foi tentar mostrar no DocumentViewer um DataGrid com paginação e tudo.
Como é de se esperar não estou aqui hoje para explicar passo a passo o código, estou aqui para dar uma solução para as pessoas que possuem o mesmo problema.
Criei uma classe chamada PrintExtensions.
Dentro dela há duas funções, uma para fazer uma cópia do DataGrid e outra para mostrar no DocumentViewer qualquer FrameworkElement, esta segunda função eu retirei do Blog do Telerik.
O arquivo com o código encontra-se aqui.
Para usar a função apenas faça:
DocumentViewer document = new DocumentViewer();
document.Document = PrintExtensions.PrintDataGrid(dataGrid1, new PrintDialog());
Espero ter ajudado e até a próxima.
Assinar:
Postagens (Atom)