Posts Tagged ‘wpf’

L’actu .NET

Sunday, May 30th, 2010

Un point sur une actualité .NET particulièrement dense ces derniers jours :

.NET

Twitter Viewer in WPF

Sunday, August 12th, 2007

I just finished the first version of the "twitter viewer" in C# with WPF. I’ve some
layout modifications to be done but the application is ready.

Download the source (Visual Studio 2008 beta 2)


Download the application (unzip and launch the .exe file)

Some screenshots :


first window

when the user clicks on an hyperlink : 


when a hyperlink is clicked

the settings page, username and password for the first version :


settings page

Convert urls to Hyperlinks with the IvalueConverter

Friday, July 20th, 2007

In my TwitterViewer in WPF I found that status can have urls in the body so they can’t
be bind directly to a TextBlock.
With a Converter I find maybe a good solution : Split the text with a regular expression,
build inline elements (simple Run for
text and Hyperlink for
urls) and put them in the Inlines property of the TextBlock :

<
Label
Margin
="8,0,8,0"
x
:
Name
="status"
Grid
.
Column
="1"
>


      <
Label
.
Content
>





<
Binding
Path
="Text"
Converter
="{StaticResource
urlConverter}"/>


       </
Label
.
Content
>


</
Label
>

And the code of the Converter implementation :

          String[] LinksText = Regex.Split((String)value, @"(\bhttp://[^
]+\b)"); TextBlock txtBlock = newTextBlock();
txtBlock.TextWrapping = System.Windows.TextWrapping.Wrap; foreach (String textSplit in LinksText)
{ if (textSplit.Length > 0) { if (textSplit.Substring(0,
1).Equals("h")) { Hyperlink textFormate
= newHyperlink(newRun(textSplit));
textFormate.NavigateUri = newUri(textSplit);
txtBlock.Inlines.Add(textFormate); } else  {
txtBlock.Inlines.Add(newRun(textSplit));
} } } return txtBlock;




Twitter Viewer

how to databind a ListView programmatically and update it with PageFunction

Monday, July 16th, 2007

I’ve read a lot of tutorials about databinding in WPF but often it’s all about XAML.
In my TwitterViewer
application
 in WPF I need to update the TwitterManager class with username
and password of the user. I choose to set the binding in code. Here is the constructor
of the main page :

          public MainPage() { InitializeComponent(); //create
a provider  odp = newObjectDataProvider();
odp.MethodName = "GetStatuses"; odp.ObjectInstance
= newTwitterManager("tewmgd", "xxxx");
odp.IsInitialLoadEnabled = false; Binding myBinding
= newBinding();
myBinding.Source = odp; //set the source of the
ItemsSource  statusList.SetBinding(ListView.ItemsSourceProperty,
myBinding); odp.Refresh(); }

With an  hyperLink the user can navigate to another page to change the settings
(username and password). The PageFunction control
allows the launching page to subscribe to the Return event and since it’s a generic
class, the return object is typesafe :

          void settingsLink_Click(object sender, RoutedEventArgs e)
{ //create a new instance of the settings page SettingsPage pageFunction
= newSettingsPage(); //subscribe
to the return event  pageFunction.Return += newReturnEventHandler<TwitterManager>
(OnSettingsReturned); this.NavigationService.Navigate(pageFunction); }
          public
          void OnSettingsReturned(object sender,ReturnEventArgs<TwitterManager>
e) { //change the source of the provider  odp.ObjectInstance
= e.Result; //refresh the provider and with it the
listview  odp.Refresh(); }


In the target page the button event
handler uses the OnReturn method to navigate backward and set the result object :

          private
          void OnClickDone(object sender, RoutedEventArgs e)
{ OnReturn(newReturnEventArgs<TwitterManager>(
newTwitterManager(this.txtUserName.Text,this.txtPassword.Text)));
}
          Update, screenshoots of the two pages :
        
          
            Twitter Viewer
          
          
            Twitter Viewer (2)
          
        

Rounded Items and alternate backgrounds in a Listview

Monday, June 18th, 2007

One of the hardest things in WPF it’s that there are many ways to reach the
same result. The same is true with other frameworks, but WPF and its language,
XAML, allow for some powerful and complex design with a large collection
of concepts : dependency properties , attached properties, control templates,
item templates, styles and so on… I’m currently writing a simple Twitter viewer
as a way to learn WPF. This "application" simply shows the xml-based feed of a user’s
friends through the API :


image

I created classes from the feed through the XSD schema generation tool (xsd.exe).
Be careful before splitting the generated classes, read the Serialization
section
on MSDN :


classDiagram

A helper class creates an HTTP request with basic authentication to get the feed :

          //object to hold twitter response 
          Statuses statuses
= null; //request
to twitter service HttpWebRequest request
= (HttpWebRequest)
WebRequest.Create("http://twitter.com/statuses/friends_timeline.xml"); //authentication info CredentialCache authInfo = newCredentialCache(); authInfo.Add(newUri(http://twitter.com/statuses/friends_timeline.xml),
"Basic", newNetworkCredential(username, password)); request.Credentials = authInfo; //make the call WebResponse response = request.GetResponse(); //deserialize response XmlSerializer mySerializer = newXmlSerializer(typeof(Statuses)); statuses = (Statuses)mySerializer.Deserialize(response.GetResponseStream()); response.Close(); listStatut = newList<Status>(statuses.status);
This method is called by the ObjectDataProvider which
provides the user and password :
          <
          ObjectDataProvider
           x
          :
          Key
          ="TwitterDataSource"
           d
          :
          IsDataSource
          ="True"
          
            
ObjectType
="{x:Type TwitterWPF:TwitterManager}" MethodName ="GetStatuses"> < ObjectDataProvider . ConstructorParameters > < sys : String > user </ sys : String > < sys : String > password </ sys : String > </ ObjectDataProvider . ConstructorParameters > </ ObjectDataProvider >


This class puts the collection returned in an ObservableCollection object
that provides notification when an item is added or removed. This can be useful
since we want to refresh the UI with a timer to get new statuses from Twitter.

I found severalarticles to
design items with alternate backgrounds in a ListView but
none works for me. They overwrite the style property of the items and they will
hide the background of the border. This border
is used to simulate rounded panels
around the text :

          <
          ListView
          .
          ItemTemplate
          > 
          
          
          <
          DataTemplate
          >
< Border Width ="400" Height ="75" CornerRadius ="10,10,10,10" Margin ="4,4,4,4"
Padding
="4,4,4,4" Background ="{Binding RelativeSource={RelativeSource AncestorType=ListViewItem},
Converter={StaticResource backgroundConverter}}">
< Grid x : Name ="statusBox" Height ="auto" Width ="auto"> < Grid . ColumnDefinitions > < ColumnDefinition Width ="0.168*" /> < ColumnDefinition Width ="0.832*" /> </ Grid . ColumnDefinitions > < Grid . RowDefinitions > < RowDefinition /> </ Grid . RowDefinitions > < Image Source ="{Binding Path=User.ProfileImageUrl}"
Grid
. Column ="0" Grid . Row ="0" x : Name ="userImage"/> < Label Margin ="8,0,8,0" x : Name ="status" Grid . Column ="1" > < TextBlock TextWrapping ="WrapWithOverflow"
Text
="{Binding Path=Text}"></ TextBlock > </ Label > </ Grid > </ Border > </ DataTemplate > </ ListView . ItemTemplate >



image

So I built an implementation of IValueConverter to
convert the binding of the background value property. I need to know the current ListViewItem,
so I provide the ancestor of type ListViewItem as the object to be converted. The
converter class finds its index inside the ListView and returns the color accordingly
:

          public
          object Convert(object value, Type targetType,

object parameter, System.Globalization.CultureInfo culture) { ListViewItem item = (ListViewItem)value; ListView listView = ItemsControl.ItemsControlFromItemContainer(item) asListView; // Get the index of a ListViewItem int index = listView.ItemContainerGenerator.IndexFromContainer(item); if (index % 2 == 0) { returnBrushes.LightBlue; } else { returnBrushes.Beige; } }


The last thing to add is the call to refresh the list of the statuses : I put
a timer that refreshes both the  ObjectDataProvider and the ListView (without
the latter the index property is not correctly returned in the converter method) :

          void TimerClock_Tick(object sender, EventArgs e)
{ ObjectDataProvider odp = Resources["TwitterDataSource"] asObjectDataProvider;
odp.Refresh(); ICollectionView dataView
= CollectionViewSource.GetDefaultView(statusList.ItemsSource);
dataView.Refresh(); }


As I said, there are surely other ways to do this, maybe even more efficiently.
But the Twitter API returning only the 20 latest statuses,  efficiently is not
an issue. And it’s a good thing because I’m still discovering the WPF world.

download
the Visual Studio Orcas solution
(beta1).

Technorati
Tags: , , ,