|
Look at his binding, IsChecked="{Binding OnOffValues[0], ElementName=control}" and the property, OnOffValues , is in the code behind of his user control. If he changes the property to a dependency property he won't get the error.
"As beings of finite lifespan, our contributions to the sum of human knowledge is one of the greatest endeavors we can undertake and one of the defining characteristics of humanity itself"
|
|
|
|
|
As explained below, it looks like he's using INPC so this is completely irrelevant.
This space for rent
|
|
|
|
|
Something like this,
Code behind
public partial class SomeControl : UserControl
{
public SomeControl()
{
InitializeComponent();
for (int i = 0; i < 20; i++)
{
OnOffValues.Add(true);
}
}
public List<bool> OnOffValues
{
get { return (List<bool>)GetValue(OnOffValuesProperty); }
set { SetValue(OnOffValuesProperty, value); }
}
public static readonly DependencyProperty OnOffValuesProperty =
DependencyProperty.Register("OnOffValues", typeof(List<bool>),
typeof(SomeControl), new PropertyMetadata(new List<bool>()));
}
XAML
<CheckBox IsChecked="{Binding Path=OnOffValues[0], RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}"/>
"As beings of finite lifespan, our contributions to the sum of human knowledge is one of the greatest endeavors we can undertake and one of the defining characteristics of humanity itself"
|
|
|
|
|
He's set the UserControl as its own DataContext. He doesn't need to create a DP if he's set the UC to implement INotifyPropertyChanged (which the property change notification suggests).
This space for rent
|
|
|
|
|
Quite true, I had taken note of that. I only supposed that the more apt approach would be to use a dependency property.
"As beings of finite lifespan, our contributions to the sum of human knowledge is one of the greatest endeavors we can undertake and one of the defining characteristics of humanity itself"
|
|
|
|
|
Not when he already set the DataContext. The issue was purely a timing issue and could be fixed with a FallbackValue.
This space for rent
|
|
|
|
|
If you check the timing of what's happening, the bind is happening as the control is being created - it happens in the InitializeComponent call in the user control. What you could do here is supply a FallbackValue so that the binding is satisfied until the point that your ViewModel is created.
This space for rent
|
|
|
|
|
Changing / setting the DataContext invokes the binding mechanism.
public MyControl()
{
OnOffValues = new List<bool>();
for (int x = 0; x < 24; x++)
{
OnOffValues.Add(true);
}
InitializeComponent();
this.DataContext = this;
}
And there is no "ElementName" in play here.
"(I) am amazed to see myself here rather than there ... now rather than then".
― Blaise Pascal
|
|
|
|
|
I have problem dragging file to the explorer.
It seems to be something to do with my current application settings.
I have a test app with hardcoded file and when the appropriate mouse event happen I trigger the following code (with hard coded file path)
var dragObj = new DataObject();
dragObj.SetFileDropList(new StringCollection() { @"H:\Temp\popeye.svg" });
DragDrop.DoDragDrop(new Window(), dragObj, DragDropEffects.Copy);
however if I do that in my other app (and I do it from the UI thread as well and with the same hard coded paths), nothing is dropped and the explorer show the forbidden cursor and the operation only complete when my mouse enter my window rect again.
I am stomped.. what could cause this code to work in one app, but not the other?
Remark: I am using the same version of the .NET Framework in both test and real app.
[EDIT]
Newsflash: this seems to be related to the UIElement I drag from being a drop target as well.
When I commented out the Drop event handlers, it dragged successfully.
Tricky, I need to be able to drop to it as well... mm....
[EDIT 2]
In my drop code I added some UIElement.MouseCapture() call. this was what prevented my code from working!
modified 21-Nov-18 11:06am.
|
|
|
|
|
I have a TreeView with EditableTextBlock in my HierarchicalDataTemplate for the TreeViewItems.
Now I have a focus problem.. when I navigate the TreeView with arrow key, the EditableTextBlock don't have Focus so I can't handle F2 (to start editing).
And also, I made my EditableTextBlock focusable, and now I have to press the directional arrow twice to change selected node with keyboard arrows...
How could I gracefully handle that, i.e.
1. arrow key down to change selected node
2. my EditableTextBlock has default an / or I can capture F2
[EDIT]
Nevermind, found a solution!
Added a property on my EditableTextBlock
FrameworkElement FocusableContainer
And listening to key event on this container.
modified 19-Nov-18 13:21pm.
|
|
|
|
|
Hi, I'm a bit late on WPF, I've developed c# Windows Forms for the last 10 years. Now I'm in the Xamarin world and I like the MVVM pattern.
I was thinking to move to WPF for Desktop developement (I need to support Windows 7).
I found myself very pleased to read the book Xamarin in action, I was looking for a great book on WPF.
Thanks.
Gassus.
|
|
|
|
|
WPF Recipes in C# 2008: A Problem-Solution Approach
(Don't let the release date throw you off).
"(I) am amazed to see myself here rather than there ... now rather than then".
― Blaise Pascal
|
|
|
|
|
Bonjour,
Lors de saisi une date erronée un cadre en rouge s'affiche en regroupant le textbox + l'icone de calendrier par contre je veux que le cadre entoure le textbox seulement.
Merci de consulter l'image ci-dessous.
https://i.postimg.cc/76mk2NFF/Capture1.jpg[^]
<datepicker>
<datepicker.selecteddate>
<binding path="DateDeb" stringformat="d" validatesondataerrors="True">
<binding.validationrules>
<communpresentation:regledatevalide>
<datepicker.resources>
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<CommunPresentation:MaskedTextbox Mask="##/##/####" Text="{Binding Path=DateDeb}" />
</controltemplate>
</setter.Value>
</setter>
|
|
|
|
|
Please post questions in English.
S'il vous plaît poser des questions en anglais.
Google Translate: When typing a wrong date a red frame is displayed by grouping the textbox + the calendar icon by cons I want the frame surrounds the textbox only.
Please see the image below.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
I'm creating a style for a button. This style creates a circle with an arrow in it. The problem is that when I mouse ever it the effect shows the button highlight.
Here's my code:
<Style x:Key="backButton" TargetType="{x:Type Button}">
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<Ellipse Grid.Column="0"
Grid.Row="0"
Canvas.Top="2"
Canvas.Left="2"
Fill="Transparent"
Height="35"
Width="35"
StrokeThickness="2"
Stroke="#6E6E6E"
Margin="2"
x:Name="part_ellipse"/>
<Path Grid.Column="0"
Grid.Row="0"
Margin="12,10,0,0"
Fill="#6E6E6E"
Data="M 0 10 L 10 0 L 10 20 Z"
x:Name="part_path"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="part_ellipse" Property="Fill" Value="#CCCCCC" />
<Setter TargetName="part_path" Property="Fill" Value="#CCCCCC" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
How do I remove the button's MouseOver effect?
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
late reply.. you probably figure out the obvious by now but...
Remove that trigger!!!
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="part_ellipse" Property="Fill" Value="#CCCCCC" />
<Setter TargetName="part_path" Property="Fill" Value="#CCCCCC" />
</Trigger>
</ControlTemplate.Triggers>
|
|
|
|
|
Hello everyone,
I've tried to follow the steps described here: https://stackoverflow.com/questions/30751663/how-to-change-mahapps-metro-dialog-content-template-width
Here, I can't understand by which way is called "newly customized" modal-dialog window.
I've tried a way that was offered at mahapps home page. This way works and calls modal-dialog window as though there was nothing customized at all. In other words mahapps.modal window is called by default.
private async void button_Click(object sender, RoutedEventArgs e)
{
await this.ShowMessageAsync("Attention", "The product is out of range");
}
Any ideas please?
modified 24-Sep-18 13:22pm.
|
|
|
|
|
Still blocked?
I am using MahApp at home, I can have a look how I do things....
|
|
|
|
|
XAML
<DataGrid Grid.Row="1"
x:Name="dataGrid"
AutoGenerateColumns="False"
BorderBrush="SteelBlue"
BorderThickness="1"
Margin="5"/>
Code Behind
private ObservableCollection<DataGridColumn> _ColumnCollection;
public ObservableCollection<DataGridColumn> ColumnCollection
{
get { return _ColumnCollection; }
set
{
if (_ColumnCollection != value)
{
_ColumnCollection = value;
RaisePropertyChanged("ColumnCollection");
}
}
}
private DataTable _Datatable;
public DataTable Datatable
{
get { return _Datatable; }
set
{
if (_Datatable != value)
{
_Datatable = value;
RaisePropertyChanged("Datatable");
}
}
}
private void CreateGrid()
{
Datatable = new DataTable();
ColumnCollection = new ObservableCollection<DataGridColumn>();
Datatable.Columns.Add("Fruit", typeof(string));
Datatable.Rows.Add("Apples");
Datatable.Rows.Add("Oranges");
Datatable.Rows.Add("Grapes");
dataGrid.Columns.Add(new DataGridTextColumn()
{
Header = "Fruit Name",
Width = new DataGridLength(200),
FontSize = 12,
Binding = new Binding("Fruit")
});
var row = Datatable.Rows[0];
dataGrid.ItemsSource = Datatable.Rows;
}
I see the column called Fruit Name, and there are 3 data rows, yet I don't see the data.
The Output Window shows 6 lines like this:
System.Windows.Data Error: 40 : BindingExpression path error: 'Fruit' property not found on 'object' ''DataRow' (HashCode=51379511)'. BindingExpression:Path=Fruit; DataItem='DataRow' (HashCode=51379511); target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String')
What am I doing wrong??
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
Using "data tables" here buys you nothing except complexity; it's part of the ADO.NET "transport mechanism" (i.e. the "back end") that you are now muddying the front-end / view with.
Use you own collection of "objects" with meaningful property names (you're trying to bind to "column names" which are in fact "column keys").
And since you control the "data source" (elements), you can also control the columns that are "auto generated" (and there is no need to add them manually in that case).
"(I) am amazed to see myself here rather than there ... now rather than then".
― Blaise Pascal
|
|
|
|
|
XAML
<DataGrid Grid.Row="1"
x:Name="dataGrid"
AutoGenerateColumns="False"
BorderBrush="SteelBlue"
BorderThickness="1"
Margin="5"/>
Code Behind
private ObservableCollection<DataGridColumn> _ColumnCollection;
public ObservableCollection<DataGridColumn> ColumnCollection
{
get { return _ColumnCollection; }
set
{
if (_ColumnCollection != value)
{
_ColumnCollection = value;
RaisePropertyChanged("ColumnCollection");
}
}
}
private DataTable _Datatable;
public DataTable Datatable
{
get { return _Datatable; }
set
{
if (_Datatable != value)
{
_Datatable = value;
RaisePropertyChanged("Datatable");
}
}
}
private void CreateGrid()
{
Datatable = new DataTable();
ColumnCollection = new ObservableCollection<DataGridColumn>();
Datatable.Columns.Add("Fruit", typeof(string));
Datatable.Rows.Add("Apples");
Datatable.Rows.Add("Oranges");
Datatable.Rows.Add("Grapes");
dataGrid.Columns.Add(new DataGridTextColumn()
{
Header = "Fruit Name",
Width = new DataGridLength(200),
FontSize = 12,
Binding = new Binding("Fruit")
});
var row = Datatable.Rows[0];
dataGrid.ItemsSource = Datatable.Rows;
}
I see the column called Fruit Name, and there are 3 data rows, yet I don't see the data.
The Output Window shows 6 lines like this:
System.Windows.Data Error: 40 : BindingExpression path error: 'Fruit' property not found on 'object' ''DataRow' (HashCode=51379511)'. BindingExpression:Path=Fruit; DataItem='DataRow' (HashCode=51379511); target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String')
What am I doing wrong??
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
I have a view called ProjectView. It has a listbox with a UserControl called ProjectDurationsView as its DataContext:
<ListBox ItemsSource="{Binding ProjectDurations}">
<ListBox.ItemTemplate>
<DataTemplate>
<ctrls:ProjectDurationsView BuildingTypeCaption="{Binding BuildingType}"
SchedulePacks="{Binding Columns}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I'm getting binding errors for both the BuildingTypeCaption and SchedulePacks properties:
"'BuildingType' property not found on 'object' ''ProjectDurationsView'"
"'Columns' property not found on 'object' ''ProjectDurationsView'"
What's the right way to bind these properties to the list item?
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
Is your user control changing its own DataContext somewhere?
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Ya that did it. I was setting DataContext=this in the CTOR
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
This is a bit long, but I'm really stuck and could use some help.
App Overview
I'm working on a construction management app. There are Projects with any number of houses. The houses are built in groups, or Jobs, where each Job can have any number of houses. For example, a project with 100 house might have 4 Jobs of 25 houses each.
Supplies are delivered to the jobs at specified intervals after the Project start date. These intervals are called Durations and the deliveries are called Drops.
So on the Project tab there is the Start Date and Max # Floors. If there are 1 and 2 story houses, then Max Floors is 2. On the Projects tab, when the Max Floors is set grids are created... one for each Story. See this picture. It shows the Settings dialog and the auto-generated DataGrids.
You can see that when # floors was set, the app read the data from the Settings and populated the list content. Each Story is a list row. The ListItem contains the BuildingType (Stories) and a single row data grid to hold the scheduled. values.
The columns in the grids are created from the Pack names. The numeric columns are used to specify the number of days past the Project Start Date when the deliveries arrive.
The Code
I followed this article.
View
<TabItem Header="Durations">
<pre>
<ListBox ItemsSource="{Binding ProjectDurations}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical"
Margin="5">
<TextBlock Text="{Binding BuildingType}"
FontSize="14"
FontWeight="Bold"/>
<DataGrid x:Name="projectPacksGrid"
AutoGenerateColumns="False"
BorderBrush="SteelBlue"
BorderThickness="1"
ItemsSource="{Binding Path=Table2}"
mcb:DataGridColumnsBehavior.BindableColumns="{Binding Columns2}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
VM
private void LoadDurationGrid()
{
if (Project.MaxFloors > 0)
{
var durationData = AppCore.BizObject.GetProjectDurationPacks(Project.Id);
ProjectDurations = new ObservableCollection<ProjectSchedulePackModel>();
var buildingTypes = BuildingTypes.Where(x => x.NumberOfFloors <= Project.MaxFloors).ToList();
foreach (var buildingType in buildingTypes)
{
List<string> data = new List<string>();
ProjectSchedulePackModel entity = new ProjectSchedulePackModel
{
BuildingType = buildingType.Caption
};
var schedulePacks = _schedulePacks.Where(x => x.BuildingTypeId == buildingType.Id).OrderBy(x => x.Sequence).ToList();
foreach (var schedulePack in schedulePacks)
{
var colName = "col" + schedulePack.Id;
entity.Table2.Columns.Add(colName, typeof(string));
Binding binding = new Binding(colName);
DataGridTextColumn column = new DataGridTextColumn
{
Header = schedulePack.Caption,
Binding = binding
};
entity.Columns2.Add(column);
var day = durationData.Where(x => x.SchedulePackId == schedulePack.Id).Select(x => x.Days).FirstOrDefault();
data.Add(day.ToString());
}
entity.Table2.Rows.Add(data.ToArray());
ProjectDurations.Add(entity);
}
}
}
DataGridColumnsBehavior Class
public class DataGridColumnsBehavior
{
public static readonly DependencyProperty BindableColumnsProperty =
DependencyProperty.RegisterAttached("BindableColumns",
typeof(ObservableCollection<DataGridColumn>),
typeof(DataGridColumnsBehavior),
new UIPropertyMetadata(null, BindableColumnsPropertyChanged));
<pre>
private static void BindableColumnsPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
{
DataGrid dataGrid = source as DataGrid;
ObservableCollection<DataGridColumn> columns = e.NewValue as ObservableCollection<DataGridColumn>;
dataGrid.Columns.Clear();
if (columns == null)
{
return;
}
foreach (DataGridColumn column in columns)
{
dataGrid.Columns.Add(column);
}
columns.CollectionChanged += (sender, e2) =>
{
NotifyCollectionChangedEventArgs ne = e2 as NotifyCollectionChangedEventArgs;
if (ne.Action == NotifyCollectionChangedAction.Reset)
{
dataGrid.Columns.Clear();
if (ne.NewItems != null)
{
foreach (DataGridColumn column in ne.NewItems)
{
dataGrid.Columns.Add(column);
}
}
}
else if (ne.Action == NotifyCollectionChangedAction.Add)
{
if (ne.NewItems != null)
{
foreach (DataGridColumn column in ne.NewItems)
{
dataGrid.Columns.Add(column);
}
}
}
else if (ne.Action == NotifyCollectionChangedAction.Move)
{
dataGrid.Columns.Move(ne.OldStartingIndex, ne.NewStartingIndex);
}
else if (ne.Action == NotifyCollectionChangedAction.Remove)
{
if (ne.OldItems != null)
{
foreach (DataGridColumn column in ne.OldItems)
{
dataGrid.Columns.Remove(column);
}
}
}
else if (ne.Action == NotifyCollectionChangedAction.Replace)
{
dataGrid.Columns[ne.NewStartingIndex] = ne.NewItems[0] as DataGridColumn;
}
};
}
public static void SetBindableColumns(DependencyObject element, ObservableCollection<DataGridColumn> value)
{
element.SetValue(BindableColumnsProperty, value);
}
public static ObservableCollection<DataGridColumn> GetBindableColumns(DependencyObject element)
{
return (ObservableCollection<datagridcolumn>)element.GetValue(BindableColumnsProperty);
}
}
Problem
When I auto-generate, then switch off the Durations tab, then back, I get an error on the line above with the arrow. See this pic with the exception: https://1drv.ms/u/s!AjBmoYAYz_v2ghfz0GFmUMkyq3Hr
What I think is happening is the binding system is trying to rebind the datagrid, but that's a guess. I'm really stuck here and could use some help.
And, if anyone has a better way, I'm all ears.
Thanks
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
modified 17-Sep-18 12:56pm.
|
|
|
|