|
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.
|
|
|
|
|
Switching tabs causes "user control loaded" to fire.
Other than that, if it's just "read only", I would've just "marked it up" and output that (instead of pretending grid "code behind" is "mvvm"; your "model" is bleeding into your "view".)
"(I) am amazed to see myself here rather than there ... now rather than then".
― Blaise Pascal
|
|
|
|
|
Hi everyone,
i need some help, doing a school work, i'm using a datagrid to display some info from my database.
<DataGrid x:Name="dataGridProduit" SelectionMode="Single" AutoGenerateColumns="false"
ItemsSource="{Binding MyProducts}"
SelectedItem="{Binding SelectedProduct, Mode=TwoWay}">
<DataGridTextColumn x:Name="Nom" Header="Nom" Binding="{Binding Name, Mode=TwoWay}" Width="*"/>
Then textbox filled with info from selectedItem
<TextBox x:Name="tbName" Height="23" Text="{Binding SelectedProduct.Name, Mode=TwoWay}"
works fine for remove,update.
But now, i'd like to add new product this way :
<Button x:Name="buttonAdd" Style="{DynamicResource ButtonStyleMainWindow}" Command="{Binding AddCommand}" CommandParameter="{Binding SelectedProduct}" />
The problem is clear, it adds but also update my selectedProduct. What would be the best solution here? other issue is, if i just fill the textboxes, then i don't raise a selectedProduct to viewmodel and then my object is null :/
i'm working now on alternative way and opening new window to add user but really i'm blind on the best way to do this
so thank u for any help u can give to me
modified 6-Sep-18 10:01am.
|
|
|
|
|
miniboom wrote: i'm working now on alternative way and opening new window to add user This is the way I do all data entry. Pop a modal dialog and allow the user to manage 1 record (SelectedProduct), save the record and update the collection.
As for your button command you do not want a SelectedProduct as the first thing you will do in the Add method is to create a new product.
I would do the following in your Add method:
Create SelectedProduct = new Product
Call the ShowDialogMethod
In your UpdateMethod
Call the ShowDialogMethod
ShowDialogMethod should
Instantiate the modal dialog (dialog view to reference the SelectedProduct)
Show the dialog
SaveDialog
Update the database
Either Add the new record to your product collection or update the SelectedProduct with the results of the database save.
There are a number of pitfalls depending on your DAL but once you have this methodology down pat it works for ALL your data entry needs.
I almost never use inline (in grid) editing, always pop a dialog it gives you dramatically more control of your record.
For simple data entry I used the same VM as the list. If the dialog is complex I will use a separate VM for it.
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
thank you very much for all these advice I already succeed in adding new product with modaldialog but it seems tricky to do the same for update at least for now. Didn't do it with Mvvm but a simple event to open the dialog in code behind :
private void button1_Click(object sender, System.Windows.RoutedEventArgs e)
{
var window = new AddProductWindow { DataContext = this.DataContext };
window.ShowDialog();
}
i'm using entity framework btw
|
|
|
|
|
miniboom wrote: i'm using entity framework
Most beginners and junior devs use EF, most senior and enterprise devs build their own DAL. I have a negative opinion of EF .
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
This is in a Class called ST :
public Class ST
{
private readonly System.Timers.Timer _timer;
private DateTime _lastScanTime;
public ST()
{
_timer = new System.Timers.Timer();
_timer.Interval = 250;
_timer.Start();
_timer.Elapsed += OnTimerElapsed;
}
public TimeSpan ScanTime { get; private set; }
private void OnTimerElapsed(object sender, ElapsedEventArgs e)
{
try
{
_timer.Stop();
ScanTime = DateTime.Now - _lastScanTime;
OnValuesRefreshed();
}
finally
{
_timer.Start();
}
_lastScanTime = DateTime.Now;
}
private void OnValuesRefreshed()
{
ValuesRefreshed?.Invoke(this, new EventArgs());
}
}
Then a value of Scantime is being transferred via MVVM pattern (ViewModel) to UI.
The major question is what do we really have valuable when we do a substraction as follows: ScanTime = DateTime.Now - _lastScanTime ? This point I can't figure out.
Thanks in advance!
|
|
|
|
|
This code would be called in a loop structure. First time it is called _LastScanTime is populated and the ScanTime is irrelevant. All subsequent calls update the ScanTime using subtraction and the _LastScanTime with the current time.
I suggest you get a book (or many books) and work through the examples if this simple logic baffles you.
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
@Holmes, my dear,
oddly enough, I knew a structure of this code, like nobody's business. I asked a bit a different stuff.
Let me repeat that: I wish I knew what we really have useful by substraction as follows: ScanTime = DateTime.Now - _lastScanTime? ? When the code is running I have a quickly alterating value 250-270 ms.
P.S. Next time, before replying, just try to read posts more carefully. As concerned books, please do me a favour, show me a book where is written for what it is being done by mentioned substraction. I'll be waiting for such useful book.
Pew
modified 5-Sep-18 1:02am.
|
|
|
|
|
So you have a ScanTime of 250-270ms.
It is generated by subtracting the current time (DateTime.Now) from the _LastScanTime which was populated by the last loop. It represents the number of milliseconds the system takes to complete the processing loop from the VM.
PS It is still a very straight forward piece of code which is staggeringly simple. Try adding
Thread.Sleep(100) after your subtraction line and see what happens.
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
Holmes> It represents the number of milliseconds the system takes to complete the processing loop from the VM.
I was waiting for this sentence.
For what this stands for? I mean, e.g. a label with mentioned milliseconds inside, on UI screen.
Just show to UI user that app is alive?
modified 5-Sep-18 4:36am.
|
|
|
|
|
Pew_new wrote: The major question is what do we really have valuable when we do a substraction as follows: ScanTime = DateTime.Now - _lastScanTime ? I cannot see anything 'valuable' in this. It merely gives you the actual elapsed time between the timer start and the first tick. Since your timer interval is set at 250 (milliseconds) it should be somewhere around that value. The question really is what this code is being used for?
|
|
|
|
|
Richard MacCutchan> The question really is what this code is being used for?
I would ask you this way.
My guess is it provides an UI user some kind of "Warning". Something like "Your PC's processor is so busy that the ScanTime went out of allowed time range." Of course in case when value is out of tolerance "window". A value is out of tolerancee "window" - text of value is highlighted with red.
modified 5-Sep-18 4:40am.
|
|
|
|