|
Hi All,
I have a Datagrid in a Window container as below
<DataGrid HorizontalAlignment="Left" Margin="103,188,0,0" VerticalAlignment="Top" Height="98" Width="313"
ItemsSource="{Binding Path=DictionaryName, Mode=TwoWay}" ></DataGrid>
And Collection in the ViewModel as below
public Dictionary<short, String> DictionaryName
{
get { return _testData.DictionaryName; }
set { _testData.DictionaryName = value; NotifyPropertyChanged("DictionaryName"); }
}
public void AddAnItem()
{
int t = DictionaryName.Max(x => x.Key) + 1;
DictionaryName.Add(short.Parse(t.ToString()), t.ToString() + "Number");
}
When Button click calls the Command then it is adding an item into the Dictionary but that is not being added into the Datagrid eventhough I kept the Mode as TwoWay?
Can anybody please help me any sort of help may be a code snippet, a link or even a suggestion also helps me?
Please its very urgent and I am new to the WPF, thanks in advance.
Thanks,
Abdul Aleem
"There is already enough hatred in the world lets spread love, compassion and affection."
|
|
|
|
|
The Dictionary<TKey, TValue> class doesn't raise an event when the collection is modified. WPF has no way to know that you've added an item.
You'll need to raise a PropertyChanged event for the collection to tell WPF that it has changed:
public void AddAnItem()
{
int t = DictionaryName.Keys.Max() + 1;
DictionaryName.Add((short)t, t + "Number");
NotifyPropertyChanged("DictionaryName");
}
NB: You can use an explicit cast to convert an int to a short ; there's no need to convert it to a string and then parse it back to a short .
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Hi,
I did that (I have added NotifyPropertyChanged method in the AddAnItem() method) still my Datagrid is not getting updated according to the collection change.
public void AddAnItem()
{
int t = DictionaryName.Keys.Max() + 1;
DictionaryName.Add((short)t, t + "Number");
NotifyPropertyChanged("DictionaryName");
}
My NotitfyProertyChanged method is written as below, do I have any error in there?
private void NotifyPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (null != handler)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
The value in the TextBox is getting added to the DictionaryName collection but is not getting displayed into the DataGrid, I tried all sorts of options, but didn't work.
<Window x:Class="TestWPFApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
xmlns:local="using:TestWPFApplication">
<Grid>
<Label Content="Enter Name" HorizontalAlignment="Left" Margin="58,62,0,0" VerticalAlignment="Top" Name="lblName"/>
<TextBox Text="{Binding Name, Mode=OneTime}" HorizontalAlignment="Left" Height="22" Margin="160,64,0,0" TextWrapping="Wrap" Name="txtName" VerticalAlignment="Top" Width="120"/>
<Button Content="Save" HorizontalAlignment="Left" Margin="180,142,0,0" VerticalAlignment="Top" Width="74" Name="btnSave"
Command="{Binding Path=TestCommand}"/>
<Button Content="Save Specific" HorizontalAlignment="Left" Margin="277,142,0,0" VerticalAlignment="Top" Width="74" Name="btnSaveSpecific"
Command="{Binding Path=TestSpecificCommand}"
CommandParameter="{Binding ElementName=txtName, Path=Text}" />
<DataGrid HorizontalAlignment="Left" Margin="103,188,0,0" VerticalAlignment="Top" Height="98" Width="313"
ItemsSource="{Binding Path=DictionaryName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" AutoGenerateColumns="True" >
<pre>
</DataGrid>
</Grid>
Anybody please help me man, even suggestion just to execute this is also fine.
Thanks,
Abdul Aleem
"There is already enough hatred in the world lets spread love, compassion and affection."
modified 13-May-16 19:48pm.
|
|
|
|
|
I tried with ObservableCollection also, with ObservableCollection datagrid is filling up a row every time (means the collection is filling up) but the value is not showing up there, can anybody please help me any sort of help.
I have my code in View as below
<Window x:Class="TestWPFApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
xmlns:local="using:TestWPFApplication">
<Grid>
<Label Content="Enter Name" HorizontalAlignment="Left" Margin="58,62,0,0" VerticalAlignment="Top" Name="lblName"/>
<TextBox Text="{Binding Name, Mode=OneWay}" HorizontalAlignment="Left" Height="22" Margin="160,64,0,0" TextWrapping="Wrap" Name="txtName" VerticalAlignment="Top" Width="120"/>
<Button Content="Save" HorizontalAlignment="Left" Margin="180,142,0,0" VerticalAlignment="Top" Width="74" Name="btnSave"
Command="{Binding Path=TestCommand}"/>
<Button Content="Save Specific" HorizontalAlignment="Left" Margin="277,142,0,0" VerticalAlignment="Top" Width="74" Name="btnSaveSpecific"
Command="{Binding Path=TestSpecificCommand}"
CommandParameter="{Binding ElementName=txtName, Path=Text}" />
<DataGrid HorizontalAlignment="Left" Margin="103,188,0,0" VerticalAlignment="Top" Height="98" Width="313"
IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding Path=DictionaryNames, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
AutoGenerateColumns="False" >
<DataGrid.Columns>
<DataGridTextColumn Header="Name of Employee" Binding="{Binding Name}" />
</DataGrid.Columns>
</DataGrid>
<pre>
</Grid>
My ViewModel
public class TestViewModel : INotifyPropertyChanged
{
TestData _testData;
public TestCommand TestCommand { get; set; }
public TestSpecificCommand TestSpecificCommand { get; set; }
public TestViewModel()
{
_testData = new TestData();
this.TestCommand = new TestCommand(this);
this.TestSpecificCommand = new TestSpecificCommand(this);
_dictionaryNames = new ObservableCollection<String>();
}
private string _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
ObservableCollection<String> _dictionaryNames;
public ObservableCollection<String> DictionaryNames
{
get { return _dictionaryNames; }
set { _dictionaryNames = value; NotifyPropertyChanged("DictionaryNames"); }
}
public Dictionary<short, String> DictionaryName
{
get { return _testData.DictionaryName; }
set { _testData.DictionaryName = value; NotifyPropertyChanged("DictionaryName"); }
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (null != handler)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
public void AddAnItem()
{
int t ;
if ((DictionaryName == null) || (DictionaryName.Count()<=0))
t = 1;
else
t = DictionaryName.Max(x => x.Key) + 1;
DictionaryName.Add((short)t, t.ToString() + "Number");
NotifyPropertyChanged("DictionaryNames");
}
public void AddAnItem(string _name)
{
int t;
if ((DictionaryName == null) || (DictionaryName.Count() <= 0))
t = 1;
else
t = (DictionaryName.Count <= 0) ? 1 : DictionaryName.Max(x => x.Key) + 1;
DictionaryName.Add(short.Parse(t.ToString()), _name);
_dictionaryNames.Add(_name);
NotifyPropertyChanged("DictionaryNames");
}
}
Thanks,
Abdul Aleem
"There is already enough hatred in the world lets spread love, compassion and affection."
|
|
|
|
|
Abdul, when adding or removing items from a collection, you have to raise an INotifyCollectionChanged event to notify the items that the number of rows has changed. This is baked into ObservableCollection.
This space for rent
|
|
|
|
|
[UPDATE]
I opened Snoop and dragged over my window. It popped up a message about "Snoop has noticed windows running in multiple dispatchers..."
As I was reading it my content appeared. IF I DON'T SNOOOP, IT BEHAVE AS BELOW.
.
.
.
.
I've got this tab control that is defined in XAML. It's an outer TabControl and it's tab items contain their own sub tabs:
I want to convert it to C# so I can load it at runtime.
<TabControl x:Name="mainTabControl"
ItemsSource="{Binding TabItems}"
SelectedItem="{Binding SelectedTabItem}"
BorderBrush="{DynamicResource MainTab.BorderBrush}"
Style="{DynamicResource MainTab.TabControl.Style}">
<pre>
<userControl:ToolBarTabItem x:Name="ScopeTabItem"
DataContext="{Binding ScopeViewModel}"
Header="{DynamicResource Maintab.Oscilloscope.Label}"
IsTabEnabled="{Binding Path=IsTabAvailable}"
TabType="Oscilloscope">
<TabControl Style="{DynamicResource InnerTabControl.Style}"
SelectedIndex="{Binding InnerTabSelectedIndex}"
ItemContainerStyle="{DynamicResource InnerTab.SelectedTabItem.Style}"<br />
ItemTemplate="{DynamicResource InnerTab.ViewPort.Header}"
ItemsSource="{Binding OscilloscopeViewPortItems}"
ContentTemplate="{StaticResource TabControlTemplate}"/>
</userControl:ToolBarTabItem>
I added the TabItems collection in the VM and bound it to the outter TabControl(above), then tried the following. The outter tab shows up OK, but the inner
private void LoadTabs()
{
TabItems = new ObservableCollection<ToolBarTabItem>();
var scopeTab = AddTab();
TabItems.Add(scopeTab);
}
private ToolBarTabItem AddTab()
{
ToolBarTabItem tab = new ToolBarTabItem();
tab.DataContext = ScopeViewModel;
tab.Header = GetStringFromResource("Maintab.Oscilloscope.Label");
tab.TabType = Tabs.Oscilloscope;
Binding isTabAvailableBinding = new Binding();
isTabAvailableBinding.Path = new PropertyPath("IsTabAvailable");
isTabAvailableBinding.Source = ScopeViewModel;
BindingOperations.SetBinding(tab, ToolBarTabItem.IsTabEnabledProperty, isTabAvailableBinding);
Style tabControlStyle = Application.Current.FindResource("InnerTabControl.Style") as Style;
Style itemContainerStyle = Application.Current.FindResource("InnerTab.SelectedTabItem.Style") as Style;
DataTemplate contentTemplate = Application.Current.FindResource("TabControlTemplate") as DataTemplate;
DataTemplate itemTemplate = Application.Current.FindResource("InnerTab.ViewPort.Header") as DataTemplate;
TabControl tabControl = new TabControl();
tabControl.Style = tabControlStyle;
tabControl.ItemContainerStyle = itemContainerStyle;
tabControl.ItemTemplate = itemTemplate;
tabControl.ContentTemplate = contentTemplate;
Binding selectedIndexBinding = new Binding();
selectedIndexBinding.Path = new PropertyPath("InnerTabSelectedIndex");
selectedIndexBinding.Source = ScopeViewModel;
BindingOperations.SetBinding(tab, TabControl.SelectedIndexProperty, selectedIndexBinding);
Binding itemSourceBinding = new Binding();
itemSourceBinding.Path = new PropertyPath("OscilloscopeViewPortItems");
itemSourceBinding.Source = ScopeViewModel;
BindingOperations.SetBinding(tab, TabControl.ItemsSourceProperty, itemSourceBinding);
tab.Content = tabControl;
return tab;
}
The resources all seem to be found OK, but I don't see the inner tab. I'm wondering if my bindings are correct. Anyone see anything wrong?
Thanks
If it's not broken, fix it until it is
modified 12-May-16 19:59pm.
|
|
|
|
|
Hi,
I have a DataGrid in WPF, how can I add a check box and need code to delete multiple selected rows from the DataGrid?
Any help a link or code snippet helps me a lot.
Thanks,
Abdul Aleem
"There is already enough hatred in the world lets spread love, compassion and affection."
|
|
|
|
|
Add a bool property to your collection - bind this to the checkbox column in the datagrid.
Add a delete button to the view
when the user clicks the button delete each item from the collection that has been checked.
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
Is there anyway I can bind this DataGrid to a method in the ViewModel directly?
Thanks,
Abdul Aleem
"There is already enough hatred in the world lets spread love, compassion and affection."
|
|
|
|
|
I have icons defined as Paths:
<!--SCOPE ICON-->
<Geometry x:Key="data1">M98.219,48.111C97...</Geometry>
<Geometry x:Key="data2">M98.219,46.948C97...</Geometry>
<UserControl x:Key="scopeIcon">
<Path>
<Path.Data>
<GeometryGroup>
<StaticResource ResourceKey="data1"/>
<StaticResource ResourceKey="data2"/>
</GeometryGroup>
</Path.Data>
</Path>
</UserControl
What I want to do now is use them in a Button control. I have subclassed Button into ImageButton:
public class MenuButton : Button
{
public string Caption
{
get { return (string)GetValue(CaptionProperty); }
set { SetValue(CaptionProperty, value); }
}
public static readonly DependencyProperty CaptionProperty =
DependencyProperty.Register("Caption", typeof(string), typeof(MenuButton), new UIPropertyMetadata(null));
}
and the style
<Style TargetType="Button"
x:Key="TestButtonStyle">
<pre>
<Setter Property="Height" Value="140"/>
<Setter Property="Width" Value="195"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type controls:MenuButton}">
<Border >
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50*"/>
<RowDefinition Height="50*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
PATH(ICON) GOES HERE <=============
<TextBlock Grid.Row="1"
Grid.Column="0"Text="{TemplateBinding Caption}"
HorizontalAlignment="Center"
VerticalAlignment="Top"
Margin="5"
Foreground="White"
FontSize="14"
TextAlignment="Center"
TextWrapping="WrapWithOverflow"/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
and it's used this way:
<controls:MenuButton Caption="{Binding Caption}"
Margin="2"
Width="100"
Style="{StaticResource TestButtonStyle}"
VerticalAlignment="Top"
Command="{Binding Path=ButtonClick}"
CommandParameter="{x:Static enums:Tabs.Oscilloscope}"/>
The question is, how in the button above to I set the path icon. It will be different for each use case. I want to set it up as part of the ControlTemplate then change it each time I add a new Menu Button.
Thanks
If it's not broken, fix it until it is
|
|
|
|
|
|
How can I handle the user clicking the icon in a Window's title bar?
Thanks
If it's not broken, fix it until it is
|
|
|
|
|
AFAIK the Title bar isn't part of the area of an application that exposes events like click. I believe you will have to create some sort of custom title bar.
I found this here on CP - WPF Custom Chrome Library[^]
|
|
|
|
|
|
|
One and a half years for your first question and this is it. Could you expand your question, just a little bit? Maybe you could identify what GAF is (other than a rather crude acronym). Then, maybe you could tell us what you are trying to achieve.
This space for rent
|
|
|
|
|
What is GAF?
There are only 10 types of people in the world, those who understand binary and those who don't.
|
|
|
|
|
I want to create some controls - a Host and a Content control. There will be one Host and many Content controls. Other developers will create Content controls and use them in the Host. For example I have a Tab control. On each tab will be a host, but each tab's Content control will be different:
MainWindow
<Window x:Class="MainWindowView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:views="clr-namespace:Views"
Title="Demo"
WindowStartupLocation="CenterScreen"
Height="800"
Width="1000">
<pre>
<Grid>
<TabControl Margin="5">
<TabItem Header="Tab 1">
<views:HostView HostContent="ContentControl_1.xaml"/>
</TabItem>
<TabItem Header="Tab 2">
<views:HostView HostContent="ContentControl_2.xaml"/>
</TabItem>
<TabItem Header="Tab 3">
<views:HostView HostContent="ContentControl_3.xaml"/>
</TabItem>
</TabControl>
</Grid>
I'm thinking that the Host control will have a ContentPresenter bound to the HostContent DP. The question is how to create the DP HostContent so that it resolves at design time?
Thanks
If it's not broken, fix it until it is
modified 3-May-16 11:38am.
|
|
|
|
|
I'm trying to use a Digital font I downloaded as a resource:
<Window x:Class="KClock.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:KClock"
WindowStyle="None"
MouseDown="Window_MouseDown"
AllowsTransparency="True"
Background="Black"
BorderBrush="Transparent"
Height="300"
Width="500">
<pre>
<Grid>
<TextBlock Text="4:40:25 pm"
Foreground="Lime"
FontSize="34">
<TextBlock.Style>
<Style>
<Setter Property="TextBlock.FontSize" Value="36" />
<Setter Property="TextElement.FontFamily" Value="Resources/DSEG14Modern-Bold" />
</Style>
</TextBlock.Style>
</TextBlock>
</Grid>
The font is in the resource, but it's unchanged in the TextBlock. What's wrong here??
Thanks
If it's not broken, fix it until it is
|
|
|
|
|
You need to specify the font family name, separated from the folder name with a # :
The folder and font family name are delimited by a # character. The folder reference may be absolute, or relative. For example, "Custom Fonts\#My Custom Font".
<TextBlock FontFamily="./resources/#Pericles Light">
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Ok, so now I have
<TextBlock Grid.Row="2"
Text="1234"
Foreground="Lime"
FontSize="40"
FontFamily="./resources/#DSEG14Modern-Bold"/>
No change
If it's not broken, fix it until it is
|
|
|
|
|
Also tried
<TextBlock Grid.Row="2"
Text="1234"
Foreground="Lime"
FontSize="40"
FontFamily="pack://application:,,,/KClock;Component/Resources/#DSEG14Modern-Bold"/>
No change
If it's not broken, fix it until it is
|
|
|
|
|
Figured it out!
<Grid>
<TextBlock Text="12345"
FontSize="40"
FontFamily="pack://application:,,,/Folder1/#DSEG14Modern-Bold" />
<TextBlock Text="12345"
FontSize="40"
FontFamily="pack://application:,,,/Folder1/#DSEG14 Modern" />
</Grid>
If it's not broken, fix it until it is
|
|
|
|
|
[UPDATE]... Sorry formatting isnt working
OVERVIEW
I'm working on a app where I need to be able produce a "report" which involves saving a piece of a view as a PNG and displaying it in Windows Photo Viewer. So I pass in the name of the topmost element and it creates the PNG and then opens the viewer. All works fine.
Now, I need to be able to exclude specific UI elements from appearing in the report. So I've written an Attached Property called ExcludeFromReport and applied it to multiple elements in my view.
Then in my class, PrintLib, I recurse the tree looking for the DP, and if it's set, I set its Visibility to Collapsed and produce the report. This work great because I can now "turn off" specific elements from appearing in the image.
PROBLEM
However.... when the property is set set to Collapsed it hides it in the UI at runtime also. So I need to find a way to store the value of the property, turn it off, then reset it. I'm an NOT looking for the default value. The default value may or may not be the value at runtime, so it can't be used.
POSSIBLE SOLUTION
Use a dictionary to hold the DP and its value before printing, then after the print routine is done, find it in the dict and reset it to its pre-print state.
CODE
Here's my class. See last method down "SetReportProperties"
public static class PrintLib
{
public static DependencyProperty ExcludeFromReportProperty =
DependencyProperty.RegisterAttached("ExcludeFromReport",
typeof(bool),
typeof(PrintLib),
new PropertyMetadata(false));
<pre>
public static void SetExcludeFromReport(DependencyObject obj, bool value)
{
obj.SetValue(ExcludeFromReportProperty, value);
}
public static bool GetExcludeFromReport(DependencyObject obj)
{
return (bool)obj.GetValue(ExcludeFromReportProperty);
}
public static void ViewImage(string filename)
{
Process process = new Process();
process.StartInfo.FileName = "rundll32.exe";
process.StartInfo.Arguments = @"C:\WINDOWS\System32\shimgvw.dll, ImageView_Fullscreen " + filename;
process.Start();
}
public static void GenerateReportFromControl(FrameworkElement element)
{
PrepareReportElements(element);
Rect rect = VisualTreeHelper.GetDescendantBounds(element);
DrawingVisual dv = new DrawingVisual();
using (DrawingContext ctx = dv.RenderOpen())
{
VisualBrush brush = new VisualBrush(element);
ctx.DrawRectangle(brush, null, new Rect(rect.Size));
}
int width = (int)element.ActualWidth;
int height = (int)element.ActualHeight;
RenderTargetBitmap rtb = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Pbgra32);
rtb.Render(dv);
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(rtb));
string filename = @"C:\temp\ReportImage.jpg";
using (FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.None))
{
encoder.Save(fs);
}
ViewImage(filename);
}
private static void PrepareReportElements(FrameworkElement element, int level = 0)
{
SetReportProperties(element);
var childCount = VisualTreeHelper.GetChildrenCount(element);
for (var i = 0; i <= childCount - 1; i++)
{
var visual = (FrameworkElement)VisualTreeHelper.GetChild(element, i);
SetReportProperties(visual);
if (VisualTreeHelper.GetChildrenCount(visual) > 0)
{
PrepareReportElements(visual, i);
}
}
}
private static void SetReportProperties(FrameworkElement element)
{
var excludeFromReportIsSet = element.ReadLocalValue(ExcludeFromReportProperty) != DependencyProperty.UnsetValue;
if (excludeFromReportIsSet)
{
var exclude = (bool)element.GetValue(ExcludeFromReportProperty);
if (exclude)
{
element.Visibility = Visibility.Collapsed;
}
}
}
}
If it's not broken, fix it until it is
|
|
|
|
|
I know this may sound like a bloody silly question by why not build a new view to support the print version flip to that and after printing return to your original view?
Oh wait, why not use a proper reporting tool SSRS or something?
Never underestimate the power of human stupidity
RAH
|
|
|
|
|