|
If you have a fixed number of rows and columns in the grid, you may be able to use a generic ItemsControl with some clever styles and templates. The ItemsControl.ItemsPanel would have the grid definition, and the ItemsTemplate would have a DataTemplate that binds the Grid.Row/Column properties to the associated properties on your object. The colorings could be set using Triggers (maybe DataTrigger instead of regular Trigger) in the template based on the value of an enumeration property.
If you have a dynamic number of rows and columns, it could be done, but is much more difficult because you have to get the actual items panel for your ItemsControl instance. I am fairly certain that this is doable, but it takes a fair bit of code to pull off.
|
|
|
|
|
Actually I'm doing this:
internal class ObsCollection<T> :ObservableCollection<T>
{
private bool _suppressNotification = false;
protected override void InsertItem(int index, T item)
{
base.InsertItem(index, item);
if (item is INotifyPropertyChanged)
(item as INotifyPropertyChanged).PropertyChanged += new PropertyChangedEventHandler(ObsCollection_PropertyChanged);
}
protected override void RemoveItem(int index)
{
if (this[index] is INotifyPropertyChanged)
(this[index] as INotifyPropertyChanged).PropertyChanged -= new PropertyChangedEventHandler(ObsCollection_PropertyChanged);
base.RemoveItem(index);
}
protected override void ClearItems()
{
for (int i = 0; i < this.Count; i++)
{
RemoveItem(i);
}
}
void ObsCollection_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
if (!_suppressNotification)
base.OnCollectionChanged(e);
}
public void AddRange(IEnumerable<T> list)
{
if (list == null)
throw new ArgumentNullException("list");
_suppressNotification = true;
foreach (T item in list)
{
Add(item);
}
_suppressNotification = false;
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
}
and in the gridControl
void s_MElementCollection_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
command.SetElementsOnGrid(ref this.grid);
}
internal void SetElementsOnGrid(ref Grid grid)
{
grid.Children.Clear();
SetHeaders(ref grid);
foreach (var item in s_Constructor.s_MElementCollection)
{
Grid.SetColumn(item, item.PositionDevice);
Grid.SetRow(item, item.PositionAntenna);
item.CommandParameter = item;
item.Command = UICommands.uiCommand;
if (item.IsEnabled)
if (item.IsError) item.Background = Brushes.OrangeRed; else item.Background = Brushes.Green;
else item.Background = Brushes.DarkRed;
grid.Children.Add(item);
}
}
Seems to work by now. What do you think about this aproach?
|
|
|
|
|
If you have something that already works, I would stick with it.
Only thing that jumps out at me is that you are passing the Grid by reference. Passing a class parameter by reference is only needed in exceptional circumstances.
|
|
|
|
|
I personally really don't like the idea of having UI elements in the collection
when WPF provides data templating to build the UI for you so you can keep your
UI and data separate.
Given that, your requirements, and the fact that I've never tried making
a custom ItemsControl before, I thought I'd play around with this.
Always fun to learn new stuff!
Here's what I came up with...
ezazazel wrote: Rule1: PositionX and PositionY inside the softwarematrix are taken out of the properties from the class
Rule2: BackgroundColor is defined by the status of an enumeration
Given these rules, I started by creating an "Obs" class, based on the name of your
originally posted "ObsCls" class. This class holds a text string, the row and column
where it should be in the grid, and a status enumeration.
So you can change an Obs objects properties and have the change magically appear in the UI,
I used INotifyPropertyChanged (dependency properties would work fine too).
I also added a class called "ObsList", which is an ObservableCollection of Obs objects.
Here's that:
using System;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Data;
using System.Windows.Controls;
using System.ComponentModel;
namespace MyNamespace
{
public class Obs : INotifyPropertyChanged
{
public enum ObsStatus
{
Off,
On
}
public event PropertyChangedEventHandler PropertyChanged;
private string _name;
public string Name
{
get
{
return _name;
}
set
{
_name = value;
OnPropertyChanged("Name");
}
}
private int _row;
public int Row
{
get
{
return _row;
}
set
{
_row = value;
OnPropertyChanged("Row");
}
}
private int _col;
public int Col
{
get
{
return _col;
}
set
{
_col = value;
OnPropertyChanged("Col");
}
}
private ObsStatus _status;
public ObsStatus Status
{
get
{
return _status;
}
set
{
_status = value;
OnPropertyChanged("Status");
}
}
public Obs(string str, int row, int col)
{
Name = str;
Row = row;
Col = col;
Status = ObsStatus.Off;
}
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
public class ObsList : ObservableCollection<Obs>
{
}
}
I also created a class derived from ObsList to use as static data in the designer:
public class ObsCls_designer : ObsList
{
public ObsCls_designer()
{
Obs newobs = new Obs("1", 0, 0);
newobs.Status = Obs.ObsStatus.Off;
Add(newobs);
newobs = new Obs("2", 1, 1);
newobs.Status = Obs.ObsStatus.On;
Add(newobs);
newobs = new Obs("3", 2, 2);
newobs.Status = Obs.ObsStatus.Off;
Add(newobs);
newobs = new Obs("4", 3, 3);
newobs.Status = Obs.ObsStatus.On;
Add(newobs);
newobs = new Obs("5", 4, 4);
newobs.Status = Obs.ObsStatus.Off;
Add(newobs);
}
}
That's it on the data side.
For the UI, you need an ItemsControl or derived to bind a collection of data to.
Since none of the built-in ItemsControls use a Grid as an ItemsPanel, I needed
to make my own custom ItemsControl. Here's the XAML in its entirety, wrapped in
a Window to test it all:
<Window x:Class="MyNamespace.TestItemsControlGridWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyNamespace"
Title="TestWindow" Height="204" Width="293" ShowInTaskbar="False" WindowStartupLocation="CenterOwner" >
<Window.Resources>
<local:ObsCls_designer x:Key="obsCls_designer" />
<local:ObsItemStyleSelector x:Key="obsItemStyleSelector"/>
</Window.Resources>
<StackPanel Width="Auto" Height="Auto">
<Border Width="Auto" Height="Auto" BorderThickness="1,1,1,1" BorderBrush="#FF505050" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="4,4,4,4">
<Grid Width="Auto" Height="Auto" HorizontalAlignment="Center" VerticalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ItemsControl Loaded="ItemsControl_Loaded" ItemContainerStyleSelector="{StaticResource obsItemStyleSelector}" ItemsSource="{Binding Source={StaticResource obsCls_designer}}" Width="Auto" Height="Auto" >
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid ShowGridLines="True">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" MinHeight="25"/>
<RowDefinition Height="Auto" MinHeight="25"/>
<RowDefinition Height="Auto" MinHeight="25"/>
<RowDefinition Height="Auto" MinHeight="25"/>
<RowDefinition Height="Auto" MinHeight="25"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" MinWidth="50"/>
<ColumnDefinition Width="Auto" MinWidth="50"/>
<ColumnDefinition Width="Auto" MinWidth="50"/>
<ColumnDefinition Width="Auto" MinWidth="50"/>
<ColumnDefinition Width="Auto" MinWidth="50"/>
</Grid.ColumnDefinitions>
</Grid>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type local:Obs}">
<Button Click="Button_Click">
<Button.Style>
<Style TargetType="{x:Type Button}" >
<Setter Property="Content" Value="{Binding Path=Name}"/>
<Setter Property="Width" Value="50"/>
<Setter Property="Height" Value="Auto"/>
<Setter Property="Margin" Value="2"/>
<Setter Property="Background" Value="#80BBBB00"/>
<Setter Property="Foreground" Value="#FF000000"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Status}" Value="On">
<Setter Property="Background" Value="#80FFFF00"/>
<Setter Property="Foreground" Value="#FFFF0000"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</Border>
<Button Content="Test" HorizontalAlignment="Center" VerticalAlignment="Center" Click="TestButton_Click"/>
</StackPanel>
</Window>
For simplicity, I inlined all the style and template stuff.
The ItemsControl.ItemTemplate is the key. It determines how items will
appear in the ItemsControl. I used a DataTemplate bound to the Obs type
which contains just a Button.
Here's the code for the ObsItemStyleSelector (thanks Gideon!) used to
bind the Obs.Row/Obs.Col properties to the Grid.Row/Grid.Column attached
properties:
public class ObsItemStyleSelector : StyleSelector
{
public override Style SelectStyle(object item, DependencyObject container)
{
Obs obs = item as Obs;
ContentPresenter cp = container as ContentPresenter;
if (null != obs && null != cp)
{
Binding binding = new Binding("Row");
binding.Source = obs;
cp.SetBinding(Grid.RowProperty, binding);
binding = new Binding("Col");
binding.Source = obs;
cp.SetBinding(Grid.ColumnProperty, binding);
}
return null;
}
}
To tie it all together and try it out, here's the code-behind for the test window:
public partial class TestItemsControlGridWindow : Window
{
private ObsList obslist = new ObsList();
public TestItemsControlGridWindow()
{
InitializeComponent();
}
private void ItemsControl_Loaded(object sender, RoutedEventArgs e)
{
ItemsControl itemscontrol = sender as ItemsControl;
itemscontrol.ItemsSource = obslist;
Obs newobs = new Obs("1", 0, 0);
newobs.Status = Obs.ObsStatus.Off;
obslist.Add(newobs);
newobs = new Obs("2", 1, 1);
newobs.Status = Obs.ObsStatus.On;
obslist.Add(newobs);
newobs = new Obs("3", 2, 2);
newobs.Status = Obs.ObsStatus.Off;
obslist.Add(newobs);
newobs = new Obs("4", 3, 3);
newobs.Status = Obs.ObsStatus.On;
obslist.Add(newobs);
newobs = new Obs("5", 4, 4);
newobs.Status = Obs.ObsStatus.Off;
obslist.Add(newobs);
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Button button = sender as Button;
Obs obs = button.DataContext as Obs;
if (obs.Status == Obs.ObsStatus.Off)
obs.Status = Obs.ObsStatus.On;
else
obs.Status = Obs.ObsStatus.Off;
}
private void TestButton_Click(object sender, RoutedEventArgs e)
{
obslist[2].Col = 0;
Obs newobs = new Obs("6", 0, 3);
newobs.Status = Obs.ObsStatus.Off;
obslist.Add(newobs);
}
}
ItemsControl_Loaded() sets the ItemControl's ItemsSource to a fresh empty ObsList
Instead of using the designer data.
Button_Click() toggles the Obs object State On or Off to test the associated UI tigger.
TestButton_Click() tests moving an item and adding an item, both by just chaging the
objects properties!
Mark Salsbery
Microsoft MVP - Visual C++
modified on Saturday, November 15, 2008 1:02 PM
|
|
|
|
|
Thanks Mark, you're great. Didn't expect anyone to do my work - nethertheless you saved my day!
Thank you again, am going to implement this next week!
So long,
eza
PS: Tried to vote for your reply, but it's too far on the right side, and I can't scroll there.
Seems to be a problem of the forum software. Anyway, it's a clear 5 from me!
|
|
|
|
|
No problem! It's a fun exercise. I'm still learning how to
do more complex WPF stuff and this one was a new challenge.
Hopefully you can get something useful out of it. Keeping the
data separate from the UI elements is much nicer and in the spirit
of WPF IMO.
I started another thread here about the Grid.Row/Grid.Column binding.
Learned something new there too
Cheers,
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
FYI
I updated the code I posted above to incorporate the binding code
discussed in the other thread.
The Obs class and the XAML changed.
Cheers,
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
I am using the MVVM pattern, and have a multi-screen data entry form. There is a single VM with an ActiveScreen property that uses INotifyPropertyChanged events. Templates are used by the View based on the current ActiveScreen.
On one of the screens, I have a ComboBox that is bound to a List<> for its ItemsSource. I am using the MVVM pattern, and the selected value of the Combobox is twoway bound to a property on my model. All works fine when you are on the screen entering data.
When the user changes the ActiveScreen, and hence a new template is used in the View, a weird thing happens. The property on the model bound to the combobox is set to NULL. Looking at the call stack, I see the ActiveScreen property change event, then a bunch of WPF code, and then my property setter. The count in the collection on the combobox at that point is 0.
It seems as if WPF does some cleanup of the combobox by removing all the items, which sets the selecteditem to null, and because of my binding, it changes my model. The net effect is I lose the data entered by the user. The other elements on that screen (textboxes, datepickers, etc) do not have this problem, so it's clearly something with the ComboBox.
Has anyone hit this before, and know of a solution? The problem is, I want the user to be able to select a blank value, so I don't know if it's the user setting the value to null or this odd series of events.
|
|
|
|
|
I found this cool plugin that you can use to export your drawings from Adobe Illustrator to XAML...it also works for WPF but you can use it for Silverlight...handy.
XAMLExport[^]
|
|
|
|
|
hi every body
i created silverlight2 application
i put image control which show an image but i want read the image from the web folder
i used this code but it didn`t work with me :
Image i2 = new Image();
i2.Source = new BitmapImage(new Uri("..\\..\\TestWeb\\Images\\session1\\2.jpg", UriKind.Relative));
and:
i2.Source = new BitmapImage(new Uri("../../TestWeb/Images/session1/2.jpg", UriKind.Relative));
any body can tell me how can i do this ???
|
|
|
|
|
|
Here's a simple wrapper around the SHBrowseForFolder() shell function.
*EDIT* Updated with more features!
using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;
namespace CommonDialogWrappers
{
public class BrowseForFolderDialog
{
#region Public Properties
public string SelectedFolder { get; protected set; }
public string Title
{
get { return BrowseInfo.lpszTitle; }
set { BrowseInfo.lpszTitle = value; }
}
public string InitialFolder { get; set; }
public string InitialExpandedFolder { get; set; }
public string OKButtonText { get; set; }
BROWSEINFOW browseInfo;
public BROWSEINFOW BrowseInfo
{
get { return browseInfo; }
protected set { browseInfo = value; }
}
public BrowseInfoFlags BrowserDialogFlags
{
get { return BrowseInfo.ulFlags; }
set { BrowseInfo.ulFlags = value; }
}
#endregion
#region Public Constructors
public BrowseForFolderDialog()
{
BrowseInfo = new BROWSEINFOW();
BrowseInfo.hwndOwner = IntPtr.Zero;
BrowseInfo.pidlRoot = IntPtr.Zero;
BrowseInfo.pszDisplayName = new String(' ', 260);
BrowseInfo.lpszTitle = "Select a folder:";
BrowseInfo.ulFlags = BrowseInfoFlags.BIF_NEWDIALOGSTYLE;
BrowseInfo.lpfn = new BrowseCallbackProc(BrowseEventHandler);
BrowseInfo.lParam = IntPtr.Zero;
BrowseInfo.iImage = -1;
}
#endregion
#region Public ShowDialog() Overloads
public Nullable<bool> ShowDialog()
{
return PInvokeSHBrowseForFolder(null);
}
public Nullable<bool> ShowDialog(Window owner)
{
return PInvokeSHBrowseForFolder(owner);
}
#endregion
#region PInvoke Stuff
private Nullable<bool> PInvokeSHBrowseForFolder(Window owner)
{
WindowInteropHelper windowhelper;
if (null != owner)
{
windowhelper = new WindowInteropHelper(owner);
BrowseInfo.hwndOwner = windowhelper.Handle;
}
IntPtr pidl = SHBrowseForFolderW(browseInfo);
if (IntPtr.Zero != pidl)
{
StringBuilder pathsb = new StringBuilder(260);
if (false != SHGetPathFromIDList(pidl, pathsb))
{
SelectedFolder = pathsb.ToString();
Marshal.FreeCoTaskMem(pidl);
return true;
}
}
return false;
}
private int BrowseEventHandler(IntPtr hwnd, MessageFromBrowser uMsg, IntPtr lParam, IntPtr lpData)
{
switch (uMsg)
{
case MessageFromBrowser.BFFM_INITIALIZED:
{
if (!string.IsNullOrEmpty(InitialExpandedFolder))
SendMessageW(hwnd, MessageToBrowser.BFFM_SETEXPANDED, new IntPtr(1), InitialExpandedFolder);
else if (!string.IsNullOrEmpty(InitialFolder))
SendMessageW(hwnd, MessageToBrowser.BFFM_SETSELECTIONW, new IntPtr(1), InitialFolder);
if (!string.IsNullOrEmpty(OKButtonText))
SendMessageW(hwnd, MessageToBrowser.BFFM_SETOKTEXT, new IntPtr(1), OKButtonText);
break;
}
case MessageFromBrowser.BFFM_SELCHANGED:
{
StringBuilder pathsb = new StringBuilder(260);
if (false != SHGetPathFromIDList(lParam, pathsb))
{
SelectedFolder = pathsb.ToString();
}
break;
}
case MessageFromBrowser.BFFM_VALIDATEFAILEDA:
{
break;
}
case MessageFromBrowser.BFFM_VALIDATEFAILEDW:
{
break;
}
case MessageFromBrowser.BFFM_IUNKNOWN:
{
break;
}
}
return 0;
}
public delegate int BrowseCallbackProc(IntPtr hwnd, MessageFromBrowser uMsg, IntPtr lParam, IntPtr lpData);
[Flags]
public enum BrowseInfoFlags : uint
{
BIF_None = 0x0000,
BIF_RETURNONLYFSDIRS = 0x0001,
BIF_DONTGOBELOWDOMAIN = 0x0002,
BIF_STATUSTEXT = 0x0004,
BIF_RETURNFSANCESTORS = 0x0008,
BIF_EDITBOX = 0x0010,
BIF_VALIDATE = 0x0020,
BIF_NEWDIALOGSTYLE = 0x0040,
BIF_USENEWUI = BIF_NEWDIALOGSTYLE | BIF_EDITBOX,
BIF_BROWSEINCLUDEURLS = 0x0080,
BIF_UAHINT = 0x0100,
BIF_NONEWFOLDERBUTTON = 0x0200,
BIF_NOTRANSLATETARGETS = 0x0400,
BIF_BROWSEFORCOMPUTER = 0x1000,
BIF_BROWSEFORPRINTER = 0x2000,
BIF_BROWSEINCLUDEFILES = 0x4000,
BIF_SHAREABLE = 0x8000
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public class BROWSEINFOW
{
public IntPtr hwndOwner;
public IntPtr pidlRoot;
public string pszDisplayName;
public string lpszTitle;
public BrowseInfoFlags ulFlags;
public BrowseCallbackProc lpfn;
public IntPtr lParam;
public int iImage;
}
public enum MessageFromBrowser : uint
{
BFFM_INITIALIZED = 1,
BFFM_SELCHANGED = 2,
BFFM_VALIDATEFAILEDA = 3,
BFFM_VALIDATEFAILEDW = 4,
BFFM_IUNKNOWN = 5
}
public enum MessageToBrowser : uint
{
WM_USER = 0x0400,
BFFM_SETSTATUSTEXTA = WM_USER + 100,
BFFM_ENABLEOK = WM_USER + 101,
BFFM_SETSELECTIONA = WM_USER + 102,
BFFM_SETSELECTIONW = WM_USER + 103,
BFFM_SETSTATUSTEXTW = WM_USER + 104,
BFFM_SETOKTEXT = WM_USER + 105,
BFFM_SETEXPANDED = WM_USER + 106
}
[DllImport("shell32.dll")]
private static extern IntPtr SHBrowseForFolderW([MarshalAs(UnmanagedType.LPStruct), In, Out] BROWSEINFOW bi);
[DllImport("shell32.dll")]
private static extern bool SHGetPathFromIDList(IntPtr pidl, StringBuilder path);
[DllImport("user32.dll")]
public static extern IntPtr SendMessageW(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
public static extern IntPtr SendMessageW(IntPtr hWnd, MessageToBrowser msg, IntPtr wParam, [MarshalAs(UnmanagedType.LPWStr)] string str);
#endregion
}
}
Sample usage:
CommonDialogWrappers.BrowseForFolderDialog dlg = new CommonDialogWrappers.BrowseForFolderDialog();
dlg.Title = "Select a folder and click OK!";
dlg.InitialExpandedFolder = @"c:\";
dlg.OKButtonText = "OK!";
if (true == dlg.ShowDialog(this))
{
MessageBox.Show(dlg.SelectedFolder, "Selected Folder");
}
Mark Salsbery
Microsoft MVP - Visual C++
modified on Wednesday, November 12, 2008 2:48 PM
|
|
|
|
|
Nicely done there sir. Nice code....
|
|
|
|
|
Heh thanks.
I think the only comments are the ones copied from SDK headers.
I matched the ShowDialog prototypes to Microsoft.Win32.OpenFileDialog's
ShowDialog() methods, hence the Nullable<bool> return type.
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
|
Thanks!
I updated the post to include all the features of the common dialog
(and <summary> info ripped from the SDK;.
Cheers,
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Hi!
I have defined a simple template to use on all windows of an application. At the beginning I wrote the style as a window resource, as shown below:
<Window.Resources>
<DataTemplate x:Key="gridDelete">
<Border Padding="2">
<Button x:Name="imgDelete" Click="imgDelete_Click" Background="Transparent" Cursor="Hand"/>
</Border>
</DataTemplate>
</Window.Resources>
In order to avoid copying this template on all the windows, I moved it to an application resource, but then I keep receiving errors stating that the imgDelete_Click can't be found. How can I define an application level template like this, and add events to the button only on the windows?
Best regards,
rferj
|
|
|
|
|
|
Hi,
In my client application (WPF) I am trying to upload a document to a sharepoint site by using WCF web service. I am able to upload documents to site upto 35 Kb. If I try to upload a file more than 35 kb in size then it throws following error message while uploading the file.
The remote server returned an unexpected response:(400) Bad Request
I have added following <binding> tag in web.config file of my WCF service
<bindings>
<wsHttpBinding>
<binding name="wshttpconfig">
<readerQuotas maxDepth="64" maxStringContentLength="2147483647"
maxArrayLength="2147483647" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
</binding>
after this I did set bindingConfiguration="wshttpconfig" in <endpoint tag>
<endpoint bindingConfiguration="wshttpconfig".....
But I still encounter the same problem.
Do I need to make any other settings in the app.config file of WCF Service
application?
Regards,
Vipul Mehta
|
|
|
|
|
Hi all.
I've created a storyboard, now I wanna run a method in secondary second of it ? means I wanna figure out when the animation reaches to the secondary second.
How can I do it ?
|
|
|
|
|
Can you provide a few more details? Are you talking about starting another storyboard when the first storyboard reaches a particular time? Easiest method might be to break the first storyboard up into two parts and when the completed event fires on the first half your could start the other storyboard.
|
|
|
|
|
lneir wrote: Can you provide a few more details?
Well, I used to work Flash. With Flash we could run a method on a specific frame , for example when the animation reach to frame 20 a method run.
Now I wanted to know ,we can run a method on a specific second in a specific storyboard ?
|
|
|
|
|
Hello,
i've some problems binding decimal values (double) with the TextBox or TextBlock control. The value is showed with the english decimal separator ( . ) and not the local one ( , ) This is an example:
http://img135.imageshack.us/img135/3120/xamlny0.png[^]
The same problem appears when i create a property in my classes then return (via the get function) a value calculated on the fly. If i bind directly the control with a double property without the get/set functions it works correctly.
Do i need to set somewhere the culture? I've tried to change it in the project settings but without solving anything.
|
|
|
|
|
If you use binding you need to make sure that you properly create the WPF compliant properties in the code. The syntax is slightly different than regular properties that only work with non-WPF controls.
Normal property:
public string Test
{
get;
set;
}
I following code is WPF compliant for interaction with binding (also found in this MSDN article[^]:
public static readonly DependencyProperty IsSpinningProperty =
DependencyProperty.Register(
"IsSpinning", typeof(Boolean),
...
);
public bool IsSpinning
{
get { return (bool)GetValue(IsSpinningProperty); }
set { SetValue(IsSpinningProperty, value); }
}
Regards,
Thomas Stockwell
Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the Universe trying to produce bigger and better idiots. So far, the Universe is winning.
Visit my Blog
|
|
|
|
|
Hi there guys.
Is there a FolderBrowserDialog in WPF ?
Thank you.
|
|
|
|
|